题目描述
已知有n本书(从1~n编号)和n个人(从1~n编号),每个人都有一个自己喜爱的书的列表,现在请你编写一个程序,设计一种分书方案,使得每个人都能获得一本书,且这本书一定要在他的喜爱列表中。
输入格式:
输入数据共若干行,第一行为一个正整数n(n <= 20)。
第2行到第n+1行,每行有n个0或1组成,第k行表示编号为k-1的人对这n本书的喜好列表,0表示不喜欢,1表示喜欢。
输出格式:
一行一个整数,表示符合条件的分配方案的总数。
输入样例
5
00110
11001
01100
00010
01001
输出样例
1
这道题想到的是递归,然后写了半天因为一个break没写导致浪费了很长的时间,我是用string类型的字符串做的,因为感觉这样会比循环数组会好一点。
#include<iostream>
using namespace std;
char every[21][21]; //用来存储输入的用户喜爱列表
int n,ans=0; //ans是可成条件的总数
void dfs(int x,int y,string str){ //x,y为当前查找的二维数组坐标,str用来存储已经找到的切符合条件的情况
int i=0;
if(every[x][y]=='1'){ //如果该用户喜欢这本书的话,进行判断
for(i=0;i<str.size();i++){ //循环str中的字符
if(str[i]-'0'==y){ //如果化为整数后等于y则证明第y本书已经被分配,如果当前不是最后一本书则递归该用户的下一本书喜爱情况
if(y<n-1){
dfs(x,y+1,str);
break;
}
break; //就是因为这个break,搞了半天,因为如果当前这本书已经被分配,那么直接跳出这个循环即可,不然代码会继续循环直至i=str.size(),会影响下面的代码,往下看。
}
}
if(i==str.size()&&i<n){ //当i==str.size()时说明i运行到结尾了,即当前第y本书没有被分配,则进行如下递归
char a;
a = y+'0'; //将y转为字符
if(y<n-1){ //如果没到末尾,先不选择该分配本书进行递归
dfs(x,y+1,str);
}
str=str+a; //将当前分配的书的位置记录
dfs(x+1,0,str); //从下一行的第一本书进行递归
}
}else{ //当用户不喜欢这本书的情况,即every[x][y]==‘0’
if(y<n-1){ //没有到末尾就往下一个即y+1递归
dfs(x,y+1,str);
}
}
if(x==n-1){ //如果到最后一行了
if(str.size()==n){ //如果记录分配书的数量等于n则证明该分配规则成立
ans++; //结果加1
return;
}
}
}
main()
{
cin>>n;
string str;
for(int i=0;i<n;i++){
cin>>str;
for(int j=0;j<str.size();j++){
every[i][j]=str[j]; //存入char类型二维数组中
}
}
dfs(0,0,""); //递归
cout<<ans<<endl;
}
我的方法可能比较乱,或者说是不好理解,看了一下跟网上其他的方法比还是有些乱,不过既然做出来了,那就记录一下,有问题请指教