题目大意:

给定一个初始集合和目标集合,有两种操作:1.合并集合中的两个元素,新元素为两个元素之和 2.分裂集合中的一个元素,得到的两个新元素之和等于原先的元素。要求用最小步数使初始集合变为目标集合,求最小步数。

其中初始集合和目标集合的元素个数都不超过10个

这是一道非常值得纪念的好题

首先一看到这个数据范围,第一反应就是状压dp了

我们首先这么考虑

如果说直接暴力的合并和分裂的话,最多需要的次数是\(n+m-2\)次,那么我们是不是可以在这个基础上进行优化呢。举个例子来看\(1,5,7,2\)-->\(2,4,3,6\)那么我们完全可以把\(1,5\)单独处理,不用将他们再跟\(2,7\)合并了,也不用额外的删除,那么这样其实就是相当于分组了。

那我们对于整体的集合,分成几个小集合,每个小集合内部又可以做同样的优化,这不就是dp的最优子结构吗

假设初始和目标都可以分成k组,那么答案应该就是\(n-m-2\times k\)了这里应该没有问题吧。

我们令\(f[i][j]\)表示初始集合中选择的元素集合是\(i\),目标集合是\(j\)的分成的组数的最大值

对于\(f[i][j]\)我们先令他等于能转移到\(f[i][j]\)的状态中的最大值,如果当前的\(sa[i]==sb[j]\)那么就说明他可以自己单独成一组,就可以++

但这里其实有一个问题就是,当\(i\)和\(j\)的\(sum\)不相同的时候,其实也有可能会++但是我们不考虑,这里有一种理解方式,是的,实际上就是因为这中间存在很多状态的合成,我们把无用的合成的状态忽略,却不会忽略用来合成它的状态,所以最后答案不会遗漏最优情况,换句话说,可以理解为就是每个不相等的情况 一定可以被不相等到相等再到不相等。其实本质是一样的

直接看代码吧

感觉这个题还是不太好理解呀

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue> using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 11; int n,m;
int sa[1 << maxn],sb[1 << maxn];
int f[1 << maxn][1 << maxn];
int a[maxn],b[maxn]; int counta(int x)
{
int cnt=0;
for (int i=1;i<=n;i++)
if (x & (1 << (i-1))) cnt+=a[i];
return cnt;
} int countb(int x)
{
int cnt=0;
for (int i=1;i<=m;i++)
if (x & (1 << (i-1))) cnt+=b[i];
return cnt;
} int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
m=read();
for (int i=1;i<=m;i++) b[i]=read();
for (int i=1;i<(1 << n);i++) sa[i]=counta(i);
for (int i=1;i<(1 << m);i++) sb[i]=countb(i);
for (int i=1;i<(1 << n);i++)
for (int j=1;j<(1 << m);j++)
{
for (int k =1;k<=n;k++)
{
int p = 1 << (k-1);
if (p&i) f[i][j]=max(f[i][j],f[i-p][j]);
}
for (int k=1;k<=m;k++)
{
int p = 1 << (k-1);
if (p&j) f[i][j]=max(f[i][j],f[i][j-p]);
}
if (sa[i]==sb[j]) f[i][j]++;
}
printf("%d",n+m-2*f[(1<<n)-1][(1<<m)-1]);
return 0;
}

bzoj2064分裂(dp)的更多相关文章

  1. 【状压dp】Bzoj2064 分裂

    Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的他把这个变成了一个数学模型. 假设中 ...

  2. bzoj2064: 分裂(状压dp)

    Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的他把这个变成了一个数学模型. 假设中 ...

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

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

  4. bzoj2064: 分裂(集合DP)

    ......咸鱼了将近一个月,因为沉迷ingress作业越来越多一直没时间搞OI呜呜呜 题目大意:有一个初始集合(n个元素)和一个目标集合(m个元素)(1<=n,m<=10),两个操作   ...

  5. [BZOJ2064]分裂 状压dp

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

  6. BZOJ2064: 分裂

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

  7. BZOJ 2064: 分裂 [DP 状压 转化]

    传送门 题意:一开始$n$块面积最后$m$块面积,面积和相等每次可以分裂或者合并,问最少几次 昨天忘发了... 不会.... 考虑最差情况,$n+m-2$所有先合并再分裂 发现只有当前后两个子集相等时 ...

  8. 【BZOJ2064】分裂 状压DP

    [BZOJ2064]分裂 Description 背景:和久必分,分久必和...题目描述:中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力.同时经常搞OI的他把这个变成了一个 ...

  9. 分裂 BZOJ2064 状压DP

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

随机推荐

  1. redis rpoplpush列表转移元素

    文档出处:redisdoc.com/list/rpoplpush.html模式: 安全的队列 Redis的列表经常被用作队列(queue),用于在不同程序之间有序地交换消息(message).一个客户 ...

  2. 状态码1xx-6xx的含义

    1xx (临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 100 (继续) 请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. 101 (切换协议) 请 ...

  3. Mysql for Mac 安装及环境配置

    一.下载及安装 首先去官网下载mac对应版本的Mysql,尾缀为.dmg的程序包 下载地址:https://dev.mysql.com/downloads/mysql/ 下载完毕后,一步步傻瓜式安装即 ...

  4. MutationObserver API

    1.概述 MutationObserver接口提供了监视对DOM树所做更改的能力.它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分. 但是,它与Mu ...

  5. 【Elasticsearch】.NetCore中Elasticsearch组件NEST的使用

    .NetCore中Elasticsearch组件NEST的使用 1. 安装Docker # 安装Docker curl -fsSL https://get.docker.com | bash -s d ...

  6. [考试总结]noip模拟42

    开始给了一个简单的题目,但我还是没有珍惜. 一个简简单单的树形 \(dp\),然而因为取模却不知道该如何比较大小.. 其实可以取 \(log\),然后我就梦中惊坐起,然后想到了魔法少女lbw 淦 然后 ...

  7. [第五篇]——Docker 镜像加速之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker 镜像加速 国内从 DockerHub 拉取镜像有时会遇到困难,此时可以配置镜像加速器.Docker 官方和国内很多云服务商都提供了国内加速器服务,例如: 科大镜像: 网易: 阿里云: 你 ...

  8. 优雅的编码,使用Optional代替if-else

    Optional是JAVA8引入的类,它其实是一个包装类,可以对所有对象进行包装, 包括null,这个特性使得我们编码可以优雅的解决空指针异常. 先编写一些测试类 class Student { pr ...

  9. [推荐]MyBatis 核心技术与面试 34 讲

    MyBatis 核心技术与面试 34 讲 职业生涯中常被问到: 如何成为某方面的高手? 如何快速搞定某项技术? 我现在的水平处于什么阶段? -- 我暗暗想,我们从小学到中学到大学,经历了大考三六九.小 ...

  10. PTA——c++类与对象

    对于给定的一个字符串,统计其中数字字符出现的次数. 类和函数接口定义: 设计一个类Solution,其中包含一个成员函数count_digits,其功能是统计传入的string类型参数中数字字符的个数 ...