状压DP
来源:互联网 发布:双系统扩大windows内存 编辑:程序博客网 时间:2024/05/21 06:23
状压DP
- 状压DP
- 对集合的一些操作
- 几道题
- 经典的
- 瞎搞的
咱都是用下标表示状态。然而,如果一个状态有20个下标,但只表示一个01值,难道要用20维数组吗?
不成!
电脑里数字都是二进制,即一个01串,就可以用一个数表示20位的状态。这个状态也可以是有20个元素的集合,所以《挑战程序设计竞赛》中叫它“针对集合的动态规划”。
理论上,下标都是unsighed int 型,而unsighed int 型是32位的,也就是能表示32维的状态。不过这样占内存很大,当32位都是1时,就会有
一般题目都是16位的。
对集合的一些操作
- 空集
∅ 0
- 单元素集 { i }
1<<i //从0开始标号
- 全集 U
(1<<n)-1 //有n个元素
- 从集合S中取元素 i
(s>>i)&1
- 并集
S∪T s|t
- 交集
S∩T s&t
- 从集合S中加入元素 i
s|(1<<i)
- 从集合S中去除元素 i
s&~(1<<i)
- 枚举全集U的子集
for(int s=1;s<(1<<n);s++)
- 枚举集合S的子集
for(int S0=S;S0;S0=(S0-1)&S)
枚举全集中大小为k的子集
//抄的p156int comp=(1<<k)-1;while(comb<(1<<n)){ //comb就是子集,处理它int x=comb&-comb,y=comb+x;//lowbit(comb)?comb=((comb&~y)/(x>>1))|y;}//一脸懵逼……
(来自《挑战程序设计竞赛》p156和蓝书p70)
几道题
经典的
UVa 10817 Headmaster’s Headache
——题意来自蓝书p95——
某校有n个教师和m个求职者,已知每人的工资和能教的课程集合,要求支付最少的工资使得每门都至少有两名教师教学,在职教师必须招聘。
输入包含多组数据,每组第一行为3个整数s,m,n,科目个数1<=s<=8,在职教师数1<=m<=20,求职者数1<=n<=100;以下m行每行描述一个在职教师,其中第一个整数c (10 000<=c<=50 000)是工资,接下来的若干整数是他的科目列表;接下来n行是申请者,格式相同,结束标志是s=0。
UVa的输入比较坑……
——下面是我瞎想的——
s不是1~8么,而且是两名教师,就可以把它“翻倍”,低8位是第一个教本科目的,高8位是第二个教本科目的,有一个就把低8位对应的变1,有两个就把高8位对应的变1,然后就是01背包啦~
还可以改为低s位高s位(大数据相当于没改),当高位有了时把低位置0。不过比较麻烦,其实内存还是可以接受的(
瞎搞的
洛谷 P2704 炮兵阵地
这一题不是很经典,但也与状压有关
他把一行压成一个数!
他把一行压成一个数!
他把一行压成一个数!
然后,这有两个骚操作,其一是移一位再与,判断有无相邻两个1,同理移两位,判隔一个的。自己与自己,就是横行;自己与上面,就是竖列。其二是筛选可能的方案数。其实这类方法很常见的,就是重复使用的东西先预处理出来,随时取用。
O(
P2704代码
//p2704#include<cstdio>#include<iostream>using namespace std;const int N=105;int mp[N],f[N][N][N],met[N],cnt[N],mcnt;//f[i][j][k]:第i行,第i行方案j,第i-1行方案k,存最大放炮个数//mp[i]:第i行的图;met[i]:可能的方案method,由地图决定//cnt[i]:这个方案能放多少炮;mcnt:可能的方案个数int main(){ int n,m; char tmp[N]; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%s",tmp); for(int j=0;j<m;j++){ mp[i]<<=1; if(tmp[j]=='H') mp[i]|=1; } }//把一横行压在一位里,山丘==1 for(int i=0;i<(1<<m);i++) if( (!(i&(i<<1)))&&(!(i&(i<<2))) ){ met[++mcnt]=i; int tm=i; while(tm){ cnt[mcnt]+=tm&1; tm>>=1; } }//选取所有方案,符合两个1之间至少两个0 for(int i=1;i<=mcnt;i++){ if(met[i]&mp[1])continue; f[1][i][1]=cnt[i]; }//第一行方案初始化,第三维其实随便 for(int i=1;i<=mcnt;i++){//第一行的方案 if(met[i]&mp[1])continue;//方案i与地图冲突 for(int j=1;j<=mcnt;j++){//第二行的方案 if(met[j]&mp[2]||//方案j与地图冲突 met[j]&met[i])continue;//方案j与方案i冲突 f[2][j][i]=cnt[j]+cnt[i];//方案i与j的数目总和 } } for(int i=3;i<=n;i++){//第i行 for(int j=1;j<=mcnt;j++){//第i行方案j if(met[j]&mp[i])continue;//方案i与地图冲突 for(int k=1;k<=mcnt;k++){//第i-1行方案k if(met[k]&mp[i-1]//方案k与地图冲突 ||met[k]&met[j])continue;//方案k与方案j冲突 for(int l=1;l<=mcnt;l++){//第i-2行方案l if(met[l]&mp[i-2]//l与地图冲突 ||met[l]&met[j]//l与j冲突 ||met[l]&met[k])continue;//l与k冲突 f[i][j][k]=max(f[i][j][k],f[i-1][k][l]+cnt[j]); } } } } int ans=0; for(int i=1;i<=mcnt;i++) for(int j=1;j<=mcnt;j++) ans=max(ans,f[n][i][j]); printf("%d",ans); return 0; }
打完已废……
- 状压dp
- 状压dp
- 状压dp
- 状压DP
- 状压DP
- 状压DP
- 状压dp
- 状压DP
- 状压DP
- 状压dp
- 状压dp
- 状压dp
- 状压DP
- 状压DP
- 状压DP
- 状压DP
- hdu 4336 概率DP 状压DP
- uva 11600 期望dp 状压dp
- 无法启动MYSQL服务”1067 进程意外终止”解决思路
- 彻底理解Java的Future模式
- Spring Cloud Stream使用细节
- ASP.NET WebForm 获取配置文件
- 软件调试笔记36
- 状压DP
- CentOS7配置默认网关
- 三大框架:Struts+Hibernate+Spring
- 解决返回数据中存在Null而导致的错误问题
- 【阿里聚安全·安全周刊】阿里双11技术十二讲直播预约|AWS S3配置错误曝光NSA陆军机密文件
- android上传多图片使用FileBody
- (转) dubbo的初步了解
- Eclipse安装反编译插件
- Linux进程间通信——使用命名管道