QOJ7602 AtCoder Quality Problem

\(black[i]\)\(i\) 这个集合内全选黑色的权值和, \(white[i]\) 同理。

考虑一个性质: \(S\) 中一定存在一个元素 \(x\) ,使得所有包含 \(x\) 的子集都是白色的。证明很简单,如果不存在这样一个元素,那么所有黑色子集的并一定会得到 \(S\) ,矛盾。

所以可以枚举 \(x\) ,计算包含 \(x\) 的集合的贡献之后把 \(x\) 删去,可以发现也是一个子问题。故有

\[dp[S] = \min_{x \in S} \{ dp[S-x] + \max \{ black[S]-black[S-x],white[S]-white[S-x] \} \} \]

枚举子集 \(O(2^n)\) ,枚举子集元素 \(O(n)\) ,总复杂度 \(O(n2^n)\)

\(\huge \mathscr{Code}\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1<<21,INF = 1e18;
int n,m,black[N],white[N],dp[N],siz;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n;
	siz = 1<<n;
	for(int i=0;i<siz;i++) cin>>black[i];
	for(int i=0;i<siz;i++) cin>>white[i];
	for(int i=0;i<n;i++){
		for(int j=0;j<siz;j++){
			if((j>>i)&1){
				black[j] += black[j^(1<<i)];
				white[j] += white[j^(1<<i)];
			}
		}
	}
	dp[0] = min(black[0],white[0]);
	for(int i=1;i<siz;i++){
		dp[i] = INF;
		for(int j=0;j<n;j++){
			if((i>>j)&1){
				dp[i] = min(dp[i],dp[i^(1<<j)] + black[i] - black[i^(1<<j)]);
				dp[i] = min(dp[i],dp[i^(1<<j)] + white[i] - white[i^(1<<j)]);
			}
		}
	}
	cout<<dp[siz-1];
	return 0;
}
posted @ 2025-07-12 16:09  OrangeRED  阅读(14)  评论(0)    收藏  举报