分书问题(详解)

大家好!今天我为大家讲的是搜索的经典题——分书问题!

题目描述

有n本书(编号为 1 − n 1-n 1n)和n个人(编号为 1 − n 1-n 1n ),每个人都有自己喜爱的书的列表。请编写一个程序,设计一种分书方案,使得每个人都获得一本书,而且这本书一定是在他的喜爱列表中

输入

第一行为一个正整数 n ( n < = 20 ) n(n<=20) nn<=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;
} 
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值