这周我们主要讨论了hdoj的2063题:过山车
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063
Problem Description
RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?
Input
输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。0
1<=N 和M<=500.接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。
Output
对于每组数据,输出一个整数,表示可以坐上过山车的最多组合数。
Sample Input
6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
0
Sample Output
3
看过题目,小组成员坚淇先想到用数组存储每个女孩,每个女孩的选择,和每个男孩的被选择情况
算法上,从选择partner最少的女孩开始,一个个赋予男生。因为题目要最多个组合,先满足选择少的女孩,因为多的可能有其他选择,没有的话,也只是损失一个组合。
然后,我提出一种情况:
6 3 4
1 1
1 2
2 3
2 4
3 1
3 3
这种情况下可以有3个组合,但判断的时候要如何找到最优解呢,因为默认第一个的话,会导致第三个女孩没有得到最优解。
然后我们就想到先赋予每种情况,再用多重循环查找和判断每个组合是否有更优解。
最后卡在了改变组合序号会怎样影响的问题。。。毕竟一开始还是要给女生默认选第一个男生,当后面组合找到更好解时,要改变组合的匹配情况,但又会对之前配好的组合产生影响,想不到如何解决。
然后,还是通过答案来反向学习了。
代码:
#include
#include
int line[510][510];//利用二维数组储存男女队员能否配对
int used[510];int boy[510];//这个数组来储存男生匹配到的女生
int K,M,N,final,a,b;
int hungary(int x)//匈牙利算法的核心代码
{
for(int j=1;j<=N;j++)
{
if(line[x][j]==1&& used[j]==0)//如果男生女生可以配对且该女生未被尝试改变配对
{
used[j]=1;
if(boy[j]==0|| hungary(boy[j]))//若男生没有配对到女生,则配对,若已配对到女生,则尝试看该男生是否还能匹配到另一个没有匹配过的女生利用 //(该处利用了递归的思想)
{
boy[j]=x;//保存男生匹配到的女生代号
return 1;
}
}
}
return 0;
}
int match()
{
for(inti=1;i<=M;i++)
{
memset(used,0,sizeof(used));
if(hungary(i)) final++;
}
return final;
}
main()
{
while(scanf("%d",&K)!=EOF)
{
if(K==0)break;
scanf("%d%d",&M,&N);
memset(line,0,sizeof(line));
memset(boy,0,sizeof(boy));
final=0;
for(int i=0;i
{
scanf("%d%d",&a,&b);
line[a][b]=1;
}
printf("%d\n",match());
}
}
代码还是很容易看懂的,重点在于这个“匈牙利算法”
匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法
不过它涉及到图论,增广路,这些我们都还不太懂,也没能通俗的解释。
所以主要记住,它用于匹配问题,运用递归。
然后这里递归其实用的很深的,我一直以为递归能不用就不用,怕会有复杂度的问题,看来还是要看实际情况。