婚姻稳定问题(Hdu 1435,Hdu 1522,Hdu 1914)

1、婚姻稳定问题描述:

有n个男人,n个女人,每个男人对每个女人之间都有一个好感度,

每个女人对每个男人也有一个好感度,求一种最佳方案,让男人,女人配对,

每个男人会去追求每个女生,使总体的好感度最高,

就是使她们的结合最稳定,就是婚姻稳定问题。

 

2、解决方法:

从为配对的男人开始,寻找最合适他的女人,

如果当前找的女人已经有男人了,判断这个女人对这两个男人的那个好感度更高,

然后将他配对。

当所有的男人都配对时,算法结束。

(之前看蓝书上的分析,说婚姻匹配最终能让所有男人选到最心仪的女人,但是女人不一定能和自己最心仪的男人结婚,

因为有可能她最喜欢的男生可能永远也没有向他告白,所以主动一点还是有好的)

 

3、例题分析:

hdu-1914

简单的,直接上模板

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 50;
int bh1[220],bh2[220],v1[maxn],v2[maxn],m1[maxn][maxn],m2[maxn][maxn],n,rk[maxn];
int a1[maxn],a2[maxn];
void fun(){
	for(int i=1;i<=n;i++){
		v1[i] = v2[i] = 0;
		rk[i] = 0;
	}
	while(1){
		int fg = 0;
		for(int i=1;i<=n;i++)
		if(!v1[i]){ //找一个单身的男人 
			fg = 1;
			int g = m1[i][++rk[i]];
			if(!v2[g]){ //当这个女人也单身的时候 
				v1[i] = g;//记录每个男人所配对的女人 
				v2[g] = i; //记录每个女人所配对的男人 
			}
			else if(m2[g][i]>m2[g][v2[g]]){ //当这个女人遇到比之前更喜欢的男人时 
				v1[v2[g]] = 0;
				v1[i] = g;
				v2[g] = i;
			}
		}
		if(!fg) break;
	}
	for(int i=1;i<=n;i++)
	printf("%c %c\n",a1[i],a2[v1[i]]);
}
int main(void){
	int T;scanf("%d",&T);
	while(T--){
		memset(bh1,0,sizeof(bh1));
		memset(bh2,0,sizeof(bh2));
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			char ss[3];scanf("%s",ss);
			bh1[ss[0]] = i;
			a1[i] = ss[0];
		}
		for(int i=1;i<=n;i++){
			char ss[3];scanf("%s",ss);
			bh2[ss[0]] = i;
			a2[i] = ss[0];
		}
		for(int i=1;i<=n;i++){
			char ss[maxn];
			scanf("%s",ss);
			int x = bh1[ss[0]],len = strlen(ss);
			for(int j=2;j<len;j++){
				int y = bh2[ss[j]];
				m1[x][j-1] = y; //记录男人x喜欢的女人y,喜欢程度从高到低 
			}
		}
		for(int i=1;i<=n;i++){
			char ss[maxn];
			scanf("%s",ss);
			int x = bh2[ss[0]],len = strlen(ss);
			for(int j=2;j<len;j++){
				int y = bh1[ss[j]];
				m2[x][y] = n-(j-1)+1; //记录女人x喜欢的男人y,喜欢程度越高,m2[x][y]的值越高 
			}
		}
		fun();
		if(T>0) printf("\n");
	}
	return 0;
}

 

 

hdu 1522

用mp记录每个男人和女人的编号即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
const int maxn = 505;
int v1[maxn],v2[maxn],m1[maxn][maxn],m2[maxn][maxn],t1,t2,rk[maxn],n;
map <string,int> mp1,mp2;
string s1[maxn],s2[maxn];
void Init(){
    for(int i=1;i<=n;i++){
        v1[i] = v2[i] = 0;
        rk[i] = 0;
        m1[i][0] = m2[i][0] = 0;
    }
    t1 = t2 = 0;
    mp1.clear();mp2.clear();
}
int ID1(string ss){
    if(!mp1.count(ss)){
        mp1[ss] = ++t1;
        s1[t1] = ss;
    }
    return mp1[ss];
}
int ID2(string ss){
    if(!mp2.count(ss)){
        mp2[ss] = ++t2;
        s2[t2] = ss;
    }
    return mp2[ss];
}
void fun(){
    while(1){
        int fg = 0;
        for(int i=1;i<=n;i++)
        if(!v1[i]){
            fg = 1;
            int g = m1[i][++rk[i]];
            if(!m1[i][g]){
                v1[i] = g;
                v2[g] = i;
            }
            else if(m2[g][i]>m2[g][v2[g]]){
                v1[v2[g]] = 0;
                v1[i] = g;
                v2[g] = i;
            }
        }
        if(!fg) break;
    }
    for(int i=1;i<=n;i++)
    cout<<s1[i]<<" "<<s2[v1[i]]<<endl;
}
int main(void){
    while(cin>>n){
        Init();
        for(int i=1;i<=n;i++){
            string ss;
            cin>>ss;
            int x = ID1(ss);
            for(int j=1;j<=n;j++){
                cin>>ss;
                int y = ID2(ss);
                m1[x][++m1[x][0]] = y;
            }
        }
        for(int i=1;i<=n;i++){
            string ss;
            cin>>ss;
            int x = ID2(ss);
            for(int j=1;j<=n;j++){
                cin>>ss;
                int y = ID1(ss);
                m2[x][y] = n-j+1;
            }
        }
        fun();
    }
    return 0;
}

 

hdu 1435

先求距离,按照距离,容量排序再去求解。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 202;
double dis[maxn];
int n,ro1[maxn],ro2[maxn],v1[maxn],v2[maxn],m1[maxn][maxn],rk[maxn],id[maxn],m2[maxn][maxn];
struct Node{
    int id;
    double x,y,z;
};
Node c1[maxn],c2[maxn];
bool cmp(int x,int y){
    if(dis[x]==dis[y]) return ro1[x]>ro1[y];
    return dis[x]<dis[y];
}
bool tmp(int x,int y){
    if(dis[x]==dis[y]) return ro2[x]>ro2[y];
    return dis[x]<dis[y];
}
double f(Node a,Node b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
void fun(){
    for(int i=1;i<=n;i++){
        v1[i] = v2[i] = 0;
        rk[i] = 0;
    }
    while(true){
        int fg = 0;
        for(int i=1;i<=n;i++)
        if(!v1[i]){
            fg = 1;
            int g = m1[i][++rk[i]];
            if(!v2[g]){
                v2[g] = i;
                v1[i] = g;
            }
            else if(m2[g][i]>m2[g][v2[g]]){
                v1[v2[g]] = 0;
                v1[i] = g;
                v2[g] = i;
            }
        }
        if(!fg) break;
    }
    for(int i=1;i<=n;i++)
    printf("%d %d\n",c1[v2[i]].id,c2[i].id);
}
int main(void){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&c1[i].id);
            scanf("%lf",&ro1[i]);
            scanf("%lf%lf%lf",&c1[i].x,&c1[i].y,&c1[i].z);
        }
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&c2[i].id);
            scanf("%lf",&ro2[i]);
            scanf("%lf%lf%lf",&c2[i].x,&c2[i].y,&c2[i].z);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dis[j] = f(c1[i],c2[j]);
                id[j] = j;
            }
            sort(id+1,id+n+1,tmp);
            for(int j=1;j<=n;j++){
                m1[i][j] = id[j];
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dis[j] = f(c2[i],c1[j]);
                id[j] = j;
            }
            sort(id+1,id+n+1,cmp);
            for(int j=1;j<=n;j++){
                m2[i][id[j]] = n-j+1;
            }
        }
        fun();
    }
    
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值