hdu 1435 Stable Match (稳定匹配)

Stable Match

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 811    Accepted Submission(s): 389
Special Judge


Problem Description
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苦思冥想也没什么进展,希望你能帮他解决这个难题.
 

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

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

Sample Input
  
  
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
 

Sample Output
  
  
3 1 1 2 2 3


稳定匹配算法详解:http://blog.csdn.net/cscmaker/article/details/8291131

http://blog.csdn.net/zy691357966/article/details/46713927

 
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<stack>
#define exp 1e-5
#define MAXN 205
using namespace std;

typedef struct location
{
    double x,y,z;
    int power,num;
}loca;

typedef struct  Distance
{
	int pos;
	int power;
	int manRank;
	double distance_;
}dis;
int c;
loca station[MAXN];   //发射站
loca receive[MAXN];   //接收站
stack<int> manstack;
int manrank[MAXN][MAXN],womenrank[MAXN][MAXN];       //分别表示男人排名为j的女生,女人心中第j个男生的排名
int manstart[MAXN],manmatch[MAXN],womensingle[MAXN];        //manstart[i]表示第i位男生选取的是心目中第几位的女生
//manmatch[i]第i位男生选中的女生的编号,womensingle[i]第i位女生对应男生的编号
double Calculatedistance(loca a,loca b)
{
    double X,Y,Z;
    X=a.x-b.x;
    Y=a.y-b.y;
    Z=a.z-b.z;
    return sqrt(X*X+Y*Y+Z*Z);
}

int cmp(dis a,dis b)
{
	if(fabs(a.distance_-b.distance_)<exp)
	{
		return a.power>b.power;
	}
	else
	{
		return a.distance_<b.distance_;
	}
}

int cmp1(dis a,dis b)
{
	return a.pos<b.pos;
}

void calculaterank(int rank[][MAXN],loca man[],loca women[],int frank[][MAXN])         //standard是要根据排序得到排名的数组,sta是
{
	int j;
	dis Sort_[MAXN];
	for(int i=0;i<c;i++)
	{
		for(j=0;j<c;j++)
		{
			Sort_[j].pos=j;            //记录编号
			Sort_[j].power=women[j].power;
			Sort_[j].distance_=Calculatedistance(man[i],women[j]);
		}
		sort(Sort_,Sort_+c,cmp);                //根据距离排序
		for(j=0;j<c;j++)
		{
			rank[i][j]=Sort_[j].pos;      //第i名男士喜欢的排名为j的女士的编号
		}
	}
	for(int i=0;i<c;i++)     //第i位女生
	{
		memset(Sort_,0,sizeof(Sort_));
		for(j=0;j<c;j++)
		{
			Sort_[j].pos=j;                        //记录编号
			Sort_[j].power=man[j].power;
			Sort_[j].distance_=Calculatedistance(women[i],man[j]);
		}
		sort(Sort_,Sort_+c,cmp);                 //根据距离排序
		/*for(j=0;j<c;j++)
		{
			Sort_[j].manRank=j;
		}
		sort(Sort_,Sort_+c,cmp1);*/
		for(j=0;j<c;j++)
		{
			frank[i][Sort_[j].pos]=j;     //第i位女生心中编号为Sort_[i].pos的男生的排名
		}
	}
	
}

void onceGS(int manpos)     //现在的男生编号为i
{
	int lovelady=manrank[manpos][manstart[manpos]];    //
	if(womensingle[lovelady]==-1)      //现在男成功脱单
	{
		womensingle[lovelady]=manpos;
		manmatch[manpos]=lovelady;
	}
	else
	{
		int oldman=womensingle[lovelady];
		if(womenrank[lovelady][oldman]<womenrank[lovelady][manpos])     //现在男逆袭失败
		{ 
			manstart[manpos]++;
			manstack.push(manpos);
		}
		else              //现在男成功逆袭脱单,过去男落单
		{
			womensingle[lovelady]=manpos;
			manmatch[manpos]=lovelady;
			manstart[oldman]++;
			manstack.push(oldman);
		}
	}


}
int main()
{
	int t,i,j;
	cin>>t;
	while(t--)
	{
		scanf("%d",&c);
        for(i=0;i<c;i++)
        {
            scanf("%d%d%lf%lf%lf",&station[i].num,&station[i].power,&station[i].x,&station[i].y,&station[i].z);
        }
        for(i=0;i<c;i++)
        {
            scanf("%d%d%lf%lf%lf",&receive[i].num,&receive[i].power,&receive[i].x,&receive[i].y,&receive[i].z);
        }
		calculaterank(manrank,station,receive,womenrank);
		memset(manstart,0,sizeof(manstart));
		for(i=0;i<c;i++)
		{
			manmatch[i]=-1;
			womensingle[i]=-1;
		}
		for(i=0;i<c;i++)    //初始化,每个男生选择自己名单上的第一个喜欢的女生
		{
			onceGS(i);
		}
		while(manstack.size()!=0)
		{
			int manpos=manstack.top();
			manstack.pop();
			onceGS(manpos);
		}

		for(i=0;i<c;i++)
		{
			printf("%d %d\n",station[womensingle[i]].num,receive[i].num);
		}

	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值