大家好!今天我为大家讲的是搜索的经典题——分书问题!
题目描述
有n本书(编号为 1 − n 1-n 1−n)和n个人(编号为 1 − n 1-n 1−n ),每个人都有自己喜爱的书的列表。请编写一个程序,设计一种分书方案,使得每个人都获得一本书,而且这本书一定是在他的喜爱列表中
输入
第一行为一个正整数 n ( n < = 20 ) n(n<=20) n(n<=20) 第2-n行,每行有n个0或者1组成,第k行表示编号为k的人对这n本书的喜爱列表,0表示不喜欢,1表示喜欢。
输出
一行一个整数,表示符合条件的分配方案的总数
样例输入
5
0 0 1 1 0
1 1 0 0 1
0 1 1 0 0
0 0 0 1 0
0 1 0 0 1
样例输出
1
看上去十分可怕的这道题,其实非常简单,类似与全排列但是多了0,1而已,So你懂了吗?
dfs:
void dfs(int x) {
if(x>n) {//抵达种数+1
cnt++;
return ;
}
for(int i=1;i<=n;i++) {
if(a[x][i]==1&&!vis[i]) {//如果ta喜欢这本书且没有被选过
vis[i]=true;//标记成被人拿了
dfs(x+1);
vis[i]=false;//回溯
}
}
}
源代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[25][25],n;
bool vis[25];
int cnt;
void dfs(int x) {
if(x>n) {
cnt++;
return ;
}
for(int i=1;i<=n;i++) {
if(a[x][i]==1&&!vis[i]) {
vis[i]=true;
dfs(x+1);
vis[i]=false;
}
}
}
signed main() {
cin>>n;
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
cin>>a[i][j];
}
}
dfs(1);//从第一个人开始
cout<<cnt;
}