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个数,从中取出一个集合,至少包含两个 ...
随机推荐
- 对网页进行截图(selenium)
import os def insert_img(driver,file_name): #获取当前路径,并转换为字符串 base_dir=str(os.path.dirname(__file__)) ...
- lintcode First Unique Number In Stream
First Unique Number In Stream 描述: Given a continuous stream of numbers, write a function that return ...
- (原创)白话KMP算法详解
引子:BF暴力算法 KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两天的总结,详细总结KMP算法如下: 初学串的模式匹配时,我们都会接触到,或者说应该能想 ...
- BZOJ 4361 isn 容斥+dp+树状数组
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4361 题意概述: 给出一个长度为N的序列A(A1,A2...AN).如果序列A不是非降的 ...
- Python中的eval
Python中的eval方法接受一个字符串参数,并且把字符串里面的内容当成Python代码来执行: eval的缺点是执行速度慢,并且会有安全风险
- C语言中动态内存的分配(malloc,realloc)
动态内存分配:根据需要随时开辟,随时释放的内存分配方式.分配时机和释放时机完全由程序员决定,由于没有数据声明,这部分空间没有名字.无法像使用变量或数组那样通过变量名或数组名引用其中的数据,只能通过指针 ...
- 2019寒假训练营寒假作业(三) 对Sketch——CM-Sketch的理解(理论题部分)
目录 实验题部分 基本题 1.简述sketch: 2.Count-min Sketch: 开放题部分 理论部分 1.解释为什么 sketch 可以省空间 2.用流程图描述Count-min sketc ...
- iOS-UISearchController用法
import "ViewController.h" @interface ViewController ()<UITableViewDelegate,UITableViewD ...
- 软工网络15团队作业4——Alpha阶段敏捷冲刺-3
一.当天站立式会议照片: 二.项目进展 昨天已完成的工作: 依靠HTML 逻辑框架等技术完成程序界面前端的实现. 明天计划完成的工作: 依靠css 逻辑框架等技术完成程序界面前端的实现. 工作中遇到的 ...
- djano modles values+ajax实现无页面刷新更新数据
做项目的过程中想通过不刷新页面的方式来进行页面数据刷新,开始使用http://www.cnblogs.com/ianduin/p/7761400.html方式将查询结果数据进行序列化.发现可以行,但是 ...