HDU 1435 简单稳定婚姻问题

题意:
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".每个实例后请输出一个空行.

想法:这是一个稳定婚姻问题,稳定婚姻问题就是n个男的和n个女的结婚,然后目的是为了让婚姻关系更稳定,在每一个男人的心中有一个排列:n个女人在自己心中的喜爱程度。每一个女人心中对每一个男人都有一个评分。例如a-b,c-d是两对夫妻,但是a更喜欢d多一点与此同时c又更满意b,那么显然会有人出轨,这样就是不稳定的关系,现在寻求一种方法使得婚姻关系变得稳定,这就需要用到一种方法:男生询问女生,女生比较男生。具体一点来说就是,在男生的心里有一个女生的排名,那么男生按照这个排名去寻找女生,那么如果这个女生没有匹配任何男生,那么这个女的就会和这个男的在一起,如果这个女生已经匹配到了男生,那么就需要将这个男生和已经和女生匹配的那个男生进行比较看看女生更喜欢谁,如果原来的男生被淘汰了,那么直接扔回队列即可,其实这种方式找下来是对男生有利的,因为男生找到的女的都是合理情况下最喜欢的女生。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=200+5;
int B_g[N][N],G_b_score[N][N];
int bg[N],gb[N];
bool mark[N][N];
int n;
struct node
{
    int num,v;
    double x,y,z;
}node1[N],node2[N];
struct nodee
{
    double dis;
    int id,v;
}fz[N];
bool cmp(nodee a,nodee b)
{
    if(a.dis==b.dis) return a.v>b.v;
    return a.dis<b.dis;
}
double Dis(node a,node b)
{
    double x=a.x-b.x;
    double y=a.y-b.y;
    double z=a.z-b.z;
    return sqrt(x*x+y*y+z*z);
}
void stable_marry()
{
    memset(mark,false,sizeof(mark));
    memset(bg,-1,sizeof(bg));
    memset(gb,-1,sizeof(gb));
    queue<int>q;
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;i++)
    {
        q.push(i);
    }
    int head,nxt;
    while(!q.empty())
    {
        head=q.front();
        q.pop();
        for(int i=1;i<=n;i++)
        {
            int nxt=B_g[head][i];
            if(mark[head][nxt]) continue;
            mark[head][nxt]=1;
            if(gb[nxt]==-1)
            {
                gb[nxt]=head;
                bg[head]=nxt;
                break;
            }
            else if(G_b_score[nxt][gb[nxt]]<G_b_score[nxt][head])
            {
                q.push(gb[nxt]);
                gb[nxt]=head;
                bg[head]=nxt;
                break;
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%lf%lf%lf",&node1[i].num,&node1[i].v,&node1[i].x,&node1[i].y,&node1[i].z);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%lf%lf%lf",&node2[i].num,&node2[i].v,&node2[i].x,&node2[i].y,&node2[i].z);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                fz[j].dis=Dis(node1[i],node2[j]);
                fz[j].id=j;
                fz[j].v=node2[j].v;
            }
            sort(fz+1,fz+n+1,cmp);
            for(int j=1;j<=n;j++)
            B_g[i][j]=fz[j].id;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                fz[j].dis=Dis(node2[i],node1[j]);
                fz[j].id=j;
                fz[j].v=node1[j].v;
            }
            sort(fz+1,fz+n+1,cmp);
            for(int j=1;j<=n;j++)
            G_b_score[i][fz[j].id]=n-j+1;
        }
        stable_marry();
        for(int i=1;i<=n;i++)
        {
            printf("%d %d\n",node1[i].num,node2[bg[i]].num);
        }
        printf("\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值