P3067 [USACO12OPEN] Balanced Cow Subsets G题解

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 22; // 左边分1的数量 -> a, 分2的 -> b,右分1 -> c, 分2 -> d 
// 只要满足 a + c == b + d 就行 
ll n, half, a[N], S, ans, cnt[1 << N], tot; 
vector < ll > G[1 << N];
unordered_map < ll, int > M;
void dfs(int x, int sum, int state) { // 枚举所有a - b
	if(x == half + 1) {
		if(!M[sum]) M[sum] = ++tot;
		// 当state是空集时,正好可以统计只选右边的情况 
		G[M[sum]].push_back(state);
		return;
	}
	dfs(x + 1, sum + a[x], state | (1 << x - 1)); // 放左边 
	dfs(x + 1, sum - a[x], state | (1 << x - 1)); // 放右边 
	dfs(x + 1, sum, state); // 不放 
}
void DFS(int x, int sum, int state) { // 枚举所有d - c
	if(x > n) {
		if(!M[sum]) return;
		int t = M[sum];
		for(int i = 0; i < G[t].size(); i++) cnt[state | G[t][i]] = true;
		// 当state是空集时,正好可以统计只有左边的情况 
		return;
	}
	DFS(x + 1, sum + a[x], state | (1 << x - 1)); // 放右边 
	DFS(x + 1, sum - a[x], state | (1 << x - 1)); // 放左边 
	DFS(x + 1, sum, state); // 不放 
}
int main() {
	cin >> n; half = n >> 1;
	for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	dfs(1, 0, 0);
	DFS(half + 1, 0, 0);
	for(int i = 1; i < (1 << n); i++) ans += cnt[i]; // 从1开始是为了避免空集 
	printf("%lld\n", ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值