BZOJ2064 分裂
Description
中国历史上上分分和和次数非常多。通读中国历史的WJMZBMR表示毫无压力。 同时经常搞OI的他把这个变成了一个数学模型。 假设中国的国土总和是不变的。 每个国家都可以用他的国土面积代替, 有两种可能,一种是两个国家合并为1个,那么新国家的面积为两者之和。 一种是一个国家分裂为2个,那么2个新国家的面积之和为原国家的面积。 WJMZBMR现在知道了很遥远的过去中国的状态,又知道了中国现在的状态,想知道至少要几次操作(分裂和合并各算一次操作),能让中国从当时状态到达现在的状态。数据保证有解。
Input
第一行一个数
Output
一行一个数表示最小次数。
分析
状压dp好题。
如果说直接暴力的合并和分裂的话,最多需要的次数是
于是发现如果上下可以被分成值相等的
然后现在就是要求
用二进制表示某一个数选或不选。如果一个数是
然后如果上面的一块和下面的一块值对应相等的话,就是所有的值加起来为
这样如果某一个子集的和为
于是令
就可以使用状压dp了。
#include<bits/stdc++.h> #define N 1<<22 using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int n,n1,n2; int sum[N],dp[N]; int main(){ n1=read();for(int i=1;i<=n1;++i) sum[1<<i-1]=read(); n2=read();for(int i=1;i<=n2;++i) sum[1<<(i+n1-1)]=-read(); n=1<<(n1+n2); for(int i=1;i<n;++i){ int tmp=i&-i;sum[i]=sum[tmp]+sum[i-tmp]; for(int j=1;j<=n1+n2;++j){ if(i&(1<<j-1)) dp[i]=max(dp[i],dp[i^(1<<j-1)]); } if(!sum[i]) dp[i]++; } printf("%d\n",n1+n2-2*dp[n-1]); return 0; }
本文作者:南风未起
本文链接:https://www.cnblogs.com/jiangchen4122/p/16840928.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步