Atcoder Beginner Contest 190 C - Bowls and Dishes

题目传送门

题目大意
我们手中拥有n个盘子,同时有k个人,每个人都有两个选择:在第Ci或者Di个盘子上放上一个球。然后我们拥有m个条件,每个条件的内容是:在第Ai和第Bi个盘子上,同时存在球。我们需要在所有放球的方案中,找到满足最多条件的放法,并输出此时满足的条件的个数。

输入格式
输入格式如下:

N M
A1 B1
.
.
.
Am Bm
K
C1 D1
.
.
.
Ck Dk

数据范围分别为:2<=n<=100,1<=m<=100,1<=Ai<Bi<=n,1<=k<=16,1<=Ci<Di<=n

输出格式
输出最多可以满足的条件的个数

样例

input1:
4 4
1 2
1 3
2 4
3 4
3
1 2
1 3
2 3
output1:
2
input2:
4 4
1 2
1 3
2 4
3 4
4
3 4
1 2
2 4
2 4
output2:
4
input3:
6 12
2 3
4 6
1 2
4 5
2 6
1 5
4 5
1 3
1 2
2 6
2 3
2 5
5
3 5
1 4
2 6
4 6
5 6
output3:
9

思路
思路其实很简单,就是把k个人放蛋糕的情况全排列一遍,然后每种情况都看一下满足多少个条件,求出最大即可,因为这里的k最大为16,所以全排列最复杂也就仅有216,等于65536,而判断是否满足情况的复杂度是线性的,所以不会超时,但最主要的是这个不确定次数的全排列应该怎么写。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int MAXN = 105;
const int MAXM = 105;

int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		vector<pair<int,int>> cond(m);//容器来装里面装m对int型的数,表示condition
		for(auto& [a,b]:cond) cin>>a>>b;//auto是自适应类型,for(auto& 数据类型:变量名)用处是返回该容器中的所有元素并进行修改,如果没有&就是创建一个复制
		int k;
		scanf("%d",&k);
		vector<pair<int,int>> choice(k);
		for(auto& [c,d]:choice) cin>>c>>d;
		
		int ans = 0;
		for(int bit = 0;bit < 1 << k;bit++)
		{
			vector<bool> ball(n);//用于保存该位置的盘子上有没有球
			for(int i = 0;i < k;i++)
			{
				const auto [c,d] = choice[i];
				ball[bit&1<<i?c:d] = 1;
			}
			int cnt = 0;
			for(auto [a,b] : cond) if(ball[a]&&ball[b]) cnt++;
			if(ans < cnt) ans = cnt;
		}
		cout << ans << endl;
	}	
	return 0;
}

这串代码主要难理解的在后半段的循环中。首先,循环变量bit,不能看作是一个十进制数,应该把他看作是一个二进制数,他的变化应该是,00000,00001,00010,00011,00100……,这么做的目的是什么呢,其实就是在全排列所有情况,把0看作是每个人的第一个选择,1是第二个选择。因此在内部循环中的ball[bit&1<<i?c:d] = 1;就是在按照bit的0和1的分配从而分配每个人球所放的位置。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值