題目描述
已知有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;
}
我的方法可能比較亂,或者說是不好理解,看了一下跟網上其他的方法比還是有些亂,不過既然做出來了,那就記錄一下,有問題請指教