首页 > ACM题库 > HDU-杭电 > HDU 1435 Stable Match-分治-[解题报告] C++
2013
12-10

HDU 1435 Stable Match-分治-[解题报告] C++

Stable Match

问题描述 :

Network 公司的BOSS 说现在他们公司建立的信号发射站和接收站经常出现信号发送接收不稳定的问题,信号的稳定度被定义为发射点到接收点的距离,距离越大,越不稳定,所以发射点跟接收点在可能的情况下应越近越好.
BOSS给8600的任务就是::建立一个匹配表,使得一个发射点对应一个接收点,对于某一个发射点来说,它的接收点离它越近那么就会更稳定,同样对于接收点也是一样的情况. 匹配的目标是使得整个网络变得稳定。,对于某2个匹配,比如,( a —- 1) ,(b—-2) ,如果发射点a 离接收点2 比 1要近,而且2 也离 发射点a要比 b 近, 那么 a 就很有可能把信号发到 2中,我们就说这个搭配是不 稳定的。同样如果发射点b 离接收点1 比 2 要近,而且1 也离 发射点b要比 a 近 ,也会出现不稳定的情 况. 而且每个点都有一个容量值,如果对于一个发射点到2个接收点的距离一样的话,它将首先选择容量大的那个. 所以8600就是要建立一个稳定的匹配,使得每个一个信号发射点对应一个接收点,并且不会出现信号不稳定的情况.
8600苦思冥想也没什么进展,希望你能帮他解决这个难题.

输入:

输入数据首先包含一个正整数N,N<=20表示测试实例的个数.每个实例首先是一个整C,C<=200表示有C个信号发射点和C个信号接收点. 接下来的C行表示 C个发射点的编号,容量和坐标,坐标为,x,y,z 3个实数(x,y,z ≥0).最后C行是C个接收点的编号,容量和坐标.

输出:

输出建立稳定搭配后各个发射点和接收点的编号,每一行代表一个搭配,前一个整数为发射点的编号,后一个为对应的接收点的编号。如果有多种情况,输出其中一种即可.如果任务不可能完成的话,输出"Impossible".每个实例后请输出一个空行.

样例输入:

1
3
1 1 60.57 57.16 69.27
2 2 26.05 61.06 11.52
3 3 9.04 58.20 56.90
1 2 280.74 12.78 316.14
2 3 305.16 267.15 87.65
3 1 240.72 312.41 217.10

样例输出:

3 1
1 2
2 3

http://acm.hdu.edu.cn/showproblem.php?pid=1435

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 205
int engage[N],n;
int boy[N][N],girl[N][N];
void Gale_Shapley(){
	queue<int> q;
	int boyid,girlid;
	for(int i=1;i<=n;i++){
		engage[i]=0;
		boy[i][0]=1;
		q.push(i);
	}
	while(!q.empty()){
		boyid=q.front();
		girlid=boy[boyid][boy[boyid][0]++];
		if(engage[girlid]==0){
			engage[girlid]=boyid;
			q.pop();
		}
		else{
			int i;
			for(i=1;i<=n;i++)
				if(girl[girlid][i]==boyid||girl[girlid][i]==engage[girlid])
					break;
			if(girl[girlid][i]==boyid){
				q.push(engage[girlid]);
				engage[girlid]=boyid;
				q.pop();
			}
		}
	}
}
struct dis{
	double s;
	double c;
	int id;
};
struct type{
	double c;
	double x,y,z;
	dis D[N];
}O[N],I[N];
void cal_dis(int x){
	for(int i=1;i<=n;i++){
		double d=0;
		d+=(O[x].x-I[i].x)*(O[x].x-I[i].x);
		d+=(O[x].y-I[i].y)*(O[x].y-I[i].y);
		d+=(O[x].z-I[i].z)*(O[x].z-I[i].z);
		d=sqrt(d);
		O[x].D[i].s=d;
		O[x].D[i].id=i;
		O[x].D[i].c=I[i].c;
		I[i].D[x].s=d;
		I[i].D[x].id=x;
		I[i].D[x].c=O[x].c;
	}
}
bool cmp(dis a,dis b){
	if(a.s==b.s)
		return a.c>b.c;
	return a.s<b.s;
}
int main(void){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			int id;
			scanf("%d",&id);
			scanf("%lf%lf%lf%lf",&O[id].c,&O[id].x,&O[id].y,&O[id].z);
		}
		for(int i=1;i<=n;i++){
			int id;
			scanf("%d",&id);
			scanf("%lf%lf%lf%lf",&I[id].c,&I[id].x,&I[id].y,&I[id].z);
		}
		for(int i=1;i<=n;i++)
			cal_dis(i);
		for(int i=1;i<=n;i++){
			sort(O[i].D+1,O[i].D+n+1,cmp);
			for(int j=1;j<=n;j++)
				boy[i][j]=O[i].D[j].id;
		}
		for(int i=1;i<=n;i++){
			sort(I[i].D+1,I[i].D+n+1,cmp);
			for(int j=1;j<=n;j++)
				girl[i][j]=I[i].D[j].id;
		}
		Gale_Shapley();
		int X[N],Y[N];
		for(int i=1;i<=n;i++){
			X[i]=i;
			Y[i]=engage[i];
		}
		for(int i=1;i<=n;i++)
			printf("%d %d\n",Y[i],X[i]);
		printf("\n");
	}
}

解题报告转自:http://blog.csdn.net/me4546/article/details/6603811


  1. 如果两个序列的最后字符不匹配(即X [M-1]!= Y [N-1])
    L(X [0 .. M-1],Y [0 .. N-1])= MAX(L(X [0 .. M-2],Y [0 .. N-1]),L(X [0 .. M-1],Y [0 .. N-1])
    这里写错了吧。