bzoj2064: 分裂(集合DP)
......咸鱼了将近一个月,因为沉迷ingress作业越来越多一直没时间搞OI呜呜呜
题目大意:有一个初始集合(n个元素)和一个目标集合(m个元素)(1<=n,m<=10),两个操作
操作①将集合里的两个数合成一个数
操作②将集合的一个数分成两个数
问对初始集合最少进行几次操作可以到达目标集合
...从来没做过集合DP题,看见这题一脸懵逼>_<
看了题解之后目瞪口呆,思路好神,又学会了新技巧(可能是我以前比较傻才不会QAQ
显然最多的次数就是将初始集合全部合成一个数然后再分成目标集合,也就是次数上界为n+m-2
如果我们可以找到初始集合的某个子集的元素和与目标集合的某个子集的元素和相等,那么我们可以少合一次,少分一次,也就是说我们每多找到一个元素和相等的子集我们的次数就可以-2。换句话说把初始集合和目标集合分成尽量多的子集让这些子集都能对应(子集元素和相等),如果能分成x个子集那么次数就是n+m-2x
所以问题转化成怎么分最多子集能相对应。f[S1][S2]为把S1和S2最多能分成几个能相对应的子集(子集元素和相等)。
当S1的元素和!=S2的元素和,就没法用上所有元素分成相对应的子集,那我们就枚举S1中的元素i或S2中的一个元素j,就有f[S1][S2]=max(f[S1^i][S2],f[S1][S2^j])
当S1的元素和==S2的元素和,我们可以用上全部元素,在这时候我们要是去掉其中一个元素,肯定会少一个子集,于是我们还是枚举S1中的元素i或S2中的一个元素j,就有f[S1][S2]=max(f[S1^i][S2],f[S1][S2^j])+1
新技巧:......原来枚举子集用二进制枚举就可以了,以前我怎么这么傻QAQ
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n,m,sum1[],sum2[],f[][];
int lowbit(int x){return x&-x;}
int main()
{
scanf("%d",&n);
for(int i=;i<n;i++)scanf("%d",&sum1[<<i]);
scanf("%d",&m);
for(int i=;i<m;i++)scanf("%d",&sum2[<<i]);
for(int i=;i<(<<n);i++)sum1[i]=sum1[i^lowbit(i)]+sum1[lowbit(i)];
for(int i=;i<(<<m);i++)sum2[i]=sum2[i^lowbit(i)]+sum2[lowbit(i)];
for(int i=;i<(<<n);i++)
for(int j=;j<(<<m);j++)
{
for(int k=;k<max(n,m);k++)
{
if(i&(<<k))f[i][j]=max(f[i^(<<k)][j],f[i][j]);
if(j&(<<k))f[i][j]=max(f[i][j^(<<k)],f[i][j]);
}
if(sum1[i]==sum2[j])f[i][j]++;
}
printf("%d\n",n+m-*f[(<<n)-][(<<m)-]);
}
bzoj2064: 分裂(集合DP)的更多相关文章
- bzoj2064分裂(dp)
题目大意: 给定一个初始集合和目标集合,有两种操作:1.合并集合中的两个元素,新元素为两个元素之和 2.分裂集合中的一个元素,得到的两个新元素之和等于原先的元素.要求用最小步数使初始集合变为目标集合, ...
- 【状压dp】Bzoj2064 分裂
Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的他把这个变成了一个数学模型. 假设中 ...
- 2018.10.24 bzoj2064: 分裂(状压dp)
传送门 状压dp好题. 考虑对于两个给出的集合. 如果没有两个元素和相等的子集,那么只能全部拼起来之后再拆开,一共需要n1+n2−2n1+n2-2n1+n2−2. 如果有呢? 那么对于没有的就是子问题 ...
- 分裂 BZOJ2064 状压DP
分析: 这个题很好啊,比起什么裸的状压DP高多了! 我们可以考虑,什么时候答案最大:全合并,之后再分裂 这样,我们必定可以得到答案,也就是说答案必定小于n+m 那么我们可以考虑,什么时候能够使答案更小 ...
- bzoj2064: 分裂(状压dp)
Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的他把这个变成了一个数学模型. 假设中 ...
- [BZOJ2064]分裂 状压dp
2064: 分裂 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 656 Solved: 404[Submit][Status][Discuss] De ...
- UVa 11825 集合dp
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #i ...
- BZOJ2064: 分裂
2064: 分裂 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 360 Solved: 220[Submit][Status][Discuss] De ...
- UVALive 7721 K - 2-ME Set 集合dp,所有数的位或来表示状态。
/** 题目:UVALive 7721 K - 2-ME Set 链接:https://vjudge.net/problem/UVALive-7721 题意:给定n个数,从中取出一个集合,至少包含两个 ...
随机推荐
- CSP201503-2:数字排序
引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...
- (原)HUD绘画贴图解析
@小道:临时存放 1\主过程 说明: a\调用DrawTextureSimple时,会将UTexure封装成CavarsItem, 若是正交投射函数执行双,最后CavarsItem.Dra ...
- [CH0304]IncDec Sequence
和NOIP2018DAY1T1类似的题目,但思维难度高多了. 这题既可以抬高路面,也可以降低路面,而且目标平面不确定,就难起来了. 但是两道题的基本思路几乎一样,同样我们将 2~n 的高度差分,1之所 ...
- HDU 2489 Minimal Ratio Tree(暴力+最小生成树)(2008 Asia Regional Beijing)
Description For a tree, which nodes and edges are all weighted, the ratio of it is calculated accord ...
- java实现几种简单的排序算法
public class SimpleAri { public static void main(String[] args) { int[] t = {11, 21, 22, 1, 6, 10, 3 ...
- (七)类、超类和子类 ——(多态,动态绑定,final类,类型转换,抽象类)
java中所有的继承都是公有继承. 在子类中的构造其内可以初始化超类的公有域,但不能初始化超类的私有域. 因此需要在子类构造前的第一行使用super()语句初始化超类的私有域. 如果超类没有不带参数的 ...
- Objective-C 反射机制
该文章属于<简书 — 刘小壮>原创,特此感谢:<简书 — 刘小壮> http://www.jianshu.com/p/5bbde2480680 了解反射机制 Objective ...
- 3dContactPointAnnotationTool开发日志(十)
要是那几个状态栏不能拖动的话岂不是显得太呆板了,于是我又参考Unity官方视频教程学习了如何实现拖动状态栏的功能,还挺简单的. 比如说要拖动这个PanelStatus面板,我只让使用者通过拖动 ...
- C#常见函数
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 分享几个.Net计划任务组件
Quartz http://www.quartz-scheduler.net/ Hangfire http://hangfire.io/ Install-Package Hangfire 使用OWIN ...