【BZOJ2064】分裂

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?(%neither_nor姜犇)

首先考虑最坏的情况,我们先将所有国家合到一起,然后再把它们一个个拆开,需要次数为n+m-2。

如果我们想让答案更优,方法就是先将所有国家合成x个国家,然后再将x个国家拆开,需要次数为n+m-2x,显然我们的x越大越好。也就是说,我们将把初始状态和结束状态分成尽可能多的集合,使得每个初始状态的集合都对应一个与它面积和相等的、结束状态的集合。

先想一种naive的做法:设f[i][j]表示已选出初始状态中的国家的状态为i(看不懂就直接认为i是一个状态),已选出结束状态中的国家的状态为j,所能形成的最多集合数。然后我们可以采用枚举子集的方法,时间复杂度惊人~

然后怎么办呢?神犇hz_lrd告诉我们,可以先假设我们已经知道了中间的状态,设初始状态中的集合为a,b,c,d,结束状态中的集合为A,B,C,D,然后我们把这些集合铺在两个序列上。第一个序列中依次放入集合a,b,c,d中的所有国家,第二个序列中依次放入A,B,C,D中的所有国家,然后对这两个序列求前缀和,其中a、A处的前缀和一定是相同的,b、B,c、C处也都相等,这就将问题转化成了:将两个序列随机排序,使得它们尽可能多的位置前缀和相等。

所以我们回到那个naive的做法,发现枚举子集根本没有必要,我们只需要枚举每个国家,一个一个加到两个状态i或j中去,一旦两个状态中的面积和相等,需要的次数就-2。为了转移更快,我们预处理出所有状态的面积和,然后转移就是O(2^(n+m)*(n+m))的了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,m;
int sn[1<<10],sm[1<<10],f[1<<10][1<<10],vn[12],vm[12];
int main()
{
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&vn[i]);
scanf("%d",&m);
for(i=1;i<=m;i++) scanf("%d",&vm[i]);
for(i=0;i<(1<<n);i++) for(j=1;j<=n;j++) if(i&(1<<j-1)) sn[i]+=vn[j];
for(i=0;i<(1<<m);i++) for(j=1;j<=m;j++) if(i&(1<<j-1)) sm[i]+=vm[j];
for(i=0;i<(1<<n);i++)
{
for(j=0;j<(1<<m);j++)
{
for(k=1;k<=n;k++) if(i&(1<<k-1)) f[i][j]=max(f[i][j],f[i^(1<<k-1)][j]);
for(k=1;k<=m;k++) if(j&(1<<k-1)) f[i][j]=max(f[i][j],f[i][j^(1<<k-1)]);
f[i][j]+=(sn[i]==sm[j])<<1;
}
}
printf("%d",n+m+2-f[(1<<n)-1][(1<<m)-1]);
return 0;
}

【BZOJ2064】分裂 状压DP的更多相关文章

  1. [BZOJ2064]分裂 状压dp

    2064: 分裂 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 656  Solved: 404[Submit][Status][Discuss] De ...

  2. BZOJ 2064: 分裂( 状压dp )

    n1+n2次一定可以满足..然后假如之前土地集合S1的子集subs1和之后土地集合S2的子集subs2相等的话...那么就少了2个+操作...所以最后答案就是n1+n2-少掉的最多操作数, 由状压dp ...

  3. 分裂 BZOJ2064 状压DP

    分析: 这个题很好啊,比起什么裸的状压DP高多了! 我们可以考虑,什么时候答案最大:全合并,之后再分裂 这样,我们必定可以得到答案,也就是说答案必定小于n+m 那么我们可以考虑,什么时候能够使答案更小 ...

  4. 2018.10.24 bzoj2064: 分裂(状压dp)

    传送门 状压dp好题. 考虑对于两个给出的集合. 如果没有两个元素和相等的子集,那么只能全部拼起来之后再拆开,一共需要n1+n2−2n1+n2-2n1+n2−2. 如果有呢? 那么对于没有的就是子问题 ...

  5. BZOJ_2064_分裂_状压DP

    BZOJ_2064_分裂_状压DP Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的 ...

  6. 状压dp学习笔记(紫例题集)

    P3451旅游景点 Tourist Attractions 这个代码其实不算是正规题解的(因为我蒟蒻)是在我们的hzoj上内存限制324MIB情况下过掉的,而且经过研究感觉不太能用滚动数组,所以那这个 ...

  7. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  8. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  9. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

随机推荐

  1. 对帝国cms、dedecms、phpcms等负载测试总结

    来自:http://www.chinaz.com/web/2013/0729/311360.shtml 担心被骂,本不想写这篇文章.犹豫良久,最终还是决定写.希望能够帮助到一些朋友,认识到数据库索引正 ...

  2. ngnix学习视频

    https://www.bilibili.com/video/av36019080/?p=1

  3. &lt;四&gt;读&lt;&lt;大话设计模式&gt;&gt;之代理模式

    代理模式我想大家即便不熟悉也都听过吧,从字面意思上看就是替别人干活的,比方代理商.在项目的实际应用中也有非常多地方用到.比方spring通过代理模式生成对象等. 代理模式的书面定义:为其它对象提供一种 ...

  4. 【BIEE】15_时间维度建立

    时间维度的建立 1.环境准备 ①新建时间维度表:TIME_DIMENSION 建立时间维度表并插入数据 ---------------创建时间维度表 create table TIME_DIMENSI ...

  5. 使用 curl() 函数实现不同站点之间注册用户的同步

    一 需求 在A站点注册一个新用户,那么,在B站点也会被同时注册 二 思路 在A站点注册的同时,调用API接口实现在B站点也会被同时注册 三 实现 主要代码如下: function http_curl( ...

  6. (二)Maven 基本概念——依赖、生命周期、仓库管理、聚合&继承

    1. 依赖配置 1.1 依赖配置主要包含如下元素: <!--添加依赖配置--> <dependencies> <!--项目要使用到junit的jar包,所以在这里添加ju ...

  7. JQuery选择器大全 前端面试送命题:面试题篇 对IOC和DI的通俗理解 c#中关于协变性和逆变性(又叫抗变)帮助理解

    JQuery选择器大全   jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 $("#myELement")    选择id值等于myElement的元素 ...

  8. 比isConnected()更靠谱的的获取socket实时连接状态!

    看到这个标题,预计非常多人会说用socket.isConnected()或者socket.isClosed()等方法来推断即可了,但其实这些方法都是訪问socket在内存驻留的状态,当socket和s ...

  9. Linux在本地使用yum安装软件

    经常遇到有的linux服务器由于特殊原因,不能连接外网,但是经常需要安装一些软件,尤其是在编译一些包的时候经常由于没有安装一些依存包而报的各种各样的错误,当你找到依存的rpm包去安装的时候,又提示你有 ...

  10. 完美运动框架(js)

    一.前言 学习js运动时,由于在实现多种不同运动效果过程中很多代码是重复的,故将其封装达到代码重用. 二.代码封装重用 function startMove(obj, json, fnEnd){ cl ...