集训队专题(5.2)1002 Stable Match

Stable Match

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 451    Accepted Submission(s): 201
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
 

Author
8600
 

Source
 

此题也是一个比较明显的稳定婚姻问题,比较麻烦的就是需要算出两两之间的距离,再进行排序,排序的过程还要考虑进去容量的关系。

#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");  
    }  
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值