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个数,从中取出一个集合,至少包含两个 ...
随机推荐
- thinkphp5使用workerman的定时器定时任务在某一个时间执行
1.首先通过 composer 安装workerman,在thinkphp5完全开发手册的扩展->coposer包->workerman有详细说明: #在项目根目录执行以下指令compos ...
- 阿里云ECS下Ubuntu 16.04系统安装python3.6.5 环境并设置为默认
一.添加python3.6安装包并安装: 二.修改系统默认python版本为3.6: 三.安装并升级pip版本: 一.添加python3.6安装包并安装: sudo apt-get install s ...
- python编程os、os.path 模块中关于文件、目录常用的函数使用方法
os模块中关于文件/目录常用的函数使用方法 函数名 使用方法 getcwd() 返回当前工作目录 chdir(path) 改变工作目录 listdir(path='.') 列举指定目录中的文件名( ...
- flask源码走读
Flask-Origin 源码版本 一直想好好理一下flask的实现,这个项目有Flask 0.1版本源码并加了注解,挺清晰明了的,我在其基础上完成了对Werkzeug的理解部分,大家如果想深入学习的 ...
- leetcode-颜色分类
颜色分类 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 0. 1 和 2 分别表示 ...
- JAVA基础学习之路(六)数组与方法参数的传递
通常,向方法中传递的都是基本数据类型,而向方法中传递数组时,就需要考虑内存的分配 public class test2 { public static void main(String args[]) ...
- 数据库Mysql的学习(五)-运算符与函数
,store,store,store,store FROM bookinfo;//加减乘除取余 //余额大于200 //余额不等于200 SELECT * FROM readerinfo WHERE ...
- 关于mysql开元数据库的几个随想
现在已经是凌晨了,昨天晚上写了我人生中的第一篇笔记,觉得没什么可写的,写了一个多小时都没写出什么,现在突然想写点东西了,这是一个比较有趣的问题,前两个月换了新工作,记得当初面试这份工作的时候面试到第三 ...
- Pipeline组Beta版本发布说明
项目名称 Pipeline 项目版本 Beta版本 负责人 北京航空航天大学计算机学院 IloveSE 小组 联系方式 http://www.cnblogs.com/IloveSE 要求发布日期 20 ...
- Java中抽象类也能实例化
在Java中抽象类真的不能实例化么? 在学习的过程中,发现了一个问题,抽象类在没有实现所有的抽象方法前是不可以通过new来构建该对象的,但是抽象方法却是可以有自己的构造方法的.这样就把我搞糊涂了,既然 ...