题目链接:
http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=559
题目大意:
有编号分别为1~N的N本书,准备分给N个人,每个人阅读兴趣用一个二维数组表示。
1:喜欢这本书;0:不喜欢这本书。
Like[i][j] = 1,i喜欢书j;Like[i][j] = 1,i不喜欢书j。
问:如何分书才能使得所有人都满意,输出第i个人分得的书的编号,如果有多个答案
输出序列数小的那一组。
思路:
序列要求从小到大,那么就从小到大递归美剧每个人喜欢的书,找到第一组答案就可以
了。用vis[]数组来判断第i本书是否被选,ans[]数组来存储输出序列。从第一个人开始选
书,到最后一个人选完书,对于每个人,找出未被选、并且自己喜欢的书进行选择,并
用vis[]标记,将序列号存入ans[]数组。然后判断剩下的人是否满足人手一本的条件(递归
判断),如果不能则将vis[]还原(恢复现场),表示不能选择该书。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int Like[130][130],vis[130],ans[130],N; int search(int M) { if(M == N) return true; for(int i = 0;i < N; ++i) //判断第i本书是否备选,第M个人是否喜欢第i本书 { if(!vis[i] && Like[M][i]) { vis[i] = 1; ans[M] = i+1; //第M个人选了第i本书 if(search(M+1)) //剩下的能否人手配一本,可以就返回 return 1; vis[i] = 0; //不可以人手配一本,就不能选择第i本书(恢复现场) } } return 0; } int main() { while(~scanf("%d",&N)) { for(int i = 0; i < N; ++i) for(int j = 0; j < N; ++j) scanf("%d",&Like[i][j]); memset(vis,0,sizeof(vis)); memset(ans,0,sizeof(ans)); search(0); for(int i = 0; i < N; ++i) if(i != N-1) printf("%d ",ans[i]); else printf("%d\n",ans[i]); } return 0; }
时间: 2024-10-04 06:33:36