NEFU559 分书问题【递归】
         
                原创
        
    
    
                
             ©著作权归作者所有:来自51CTO博客作者ITCharge的原创作品,请联系作者获取转载授权,否则将追究法律责任        
            
                    
                
题目链接:
http:///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;
}