分类
标签
2-SAT AC自动机 BFS CDQ dfs DP fail树 FFT FFT&NTT FWT hash KD-Tree KMP LCA SPFA STL Tarjan Treap Trie 主席树 乱搞 二分 二分图匹配 二分答案 二维SPFA 交互 位运算 其他 最小生成树 分块 区间DP 半平面交 博弈论 可持久化 可持久化Trie树 后缀数组 图库 平衡树 并查集 插头DP 数学 数论 无旋Treap 日记 暴力 权值树状数组 栈 树DP 树套树 树状数组 树贪心 概率DP 模拟 欧拉定理 点分治 状压DP 生成函数 矩阵乘 线性规划 线段树 组合 网络流 群论 莫比乌斯反演 计算几何 贪心 费用流 高斯消元
630 字
3 分钟
BZOJ 2064 分裂 状压DP
Description
背景: 和久必分,分久必和。。。 题目描述: 中国历史上上分分和和次数非常多。。通读中国历史的WJMZBMR表示毫无压力。 同时经常搞OI的他把这个变成了一个数学模型。 假设中国的国土总和是不变的。 每个国家都可以用他的国土面积代替, 又两种可能,一种是两个国家合并为1个,那么新国家的面积为两者之和。 一种是一个国家分裂为2个,那么2个新国家的面积之和为原国家的面积。 WJMZBMR现在知道了很遥远的过去中国的状态,又知道了中国现在的状态,想知道至少要几次操作(分裂和合并各算一次操作),能让中国从当时状态到达现在的状态。
Input
第一行一个数n1,表示当时的块数,接下来n1个数分别表示各块的面积。 第二行一个数n2,表示现在的块,接下来n2个数分别表示各块的面积。
Output
一行一个数表示最小次数。
Sample Input
1 6
3 1 2 3
Sample Output
2
数据范围:
对于100%的数据,n1,n2<=10,每个数<=50
对于30%的数据,n1,n2<=6,
题解
状压DP 首先可以知道用次一定可以实现
所以我们考虑减少次数。
如果原集合能分出来一块与新集合中的一块大小相同。
那么这是一个子问题, 他的答案也是
同样剩下的集合也是如此。 这样我们就把答案减小了2。
然后可以看出我们需要尽可能多的将集合分为几部分。 每部分对应相等。
这可以用状压DP来解决。
可以将新集合中所有值设为相反数, 这样就可以求和为0就可以了。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[100];
int S[(1 << 20) + 1], f[(1 << 20) + 1];
int main()
{
int n, m;
int cnt = 0;
scanf ("%d", &n);
for (cnt = 1; cnt <= n; cnt++)
scanf ("%d", &a[cnt]);
scanf ("%d", &m);
n += m;
for (; cnt <= n; cnt++)
scanf ("%d", &a[cnt]), a[cnt] = -a[cnt];
int N = (1 << n) - 1;
for (int i = 1; i <= N; i++)
{
int j = 0;
for (j = 1; j <= n; j++)
if (i & (1 << (j - 1)))
break;
S[i] = S[i ^ (1 << (j - 1))] + a[j];
for (j = 1; j <= n; j++)
if (i & (1 << (j - 1)))
f[i] = max(f[i], f[i ^ (1 << (j - 1))] + (!S[i]));
}
printf ("%d", n - f[N] * 2);
}