状压DP总结
状态压缩就是将一行的状态压成一个二进制数,这个数的二进制形式反映了这一行的情况
比如0100111的意义为:这一排的第一个数没被使用,第二个被占用了,第三四个没被占用,第五六七个被占用
我们知道位运算和状压DP一样,也是在二进制下进行的,所以位运算往往可以解决很多问题
我们来看看状压DP(位运算)的常用操作:

有了这些位运算的帮助,我们便可以更加容易的对每一排的状态进行处理
我们来看到状态压缩DP的经典问题(博主正在缓慢更新ing)
一、P1879 [USACO06NOV]玉米田Corn Fields
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define maxn 20
#define mod 100000000
il int read()
{
re int x=0,k=1;re char c=getchar();
while(c<'0'||c>'9'){if(c=='-') k=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*k;
}
int m,n,a[maxn][maxn],s[maxn],dp[maxn][1<<maxn];
int main()
{
n=read(),m=read();
for(re int i=1;i<=n;++i)
{
for(re int j=1;j<=m;++j)
{
a[i][j]=read();
s[i]<<=1;
s[i]+=a[i][j];
}
}
dp[0][0]=1;
for(re int i=1;i<=n;++i)
{
for(re int j=0;j<(1<<m);++j)//这一行状态
{
if((s[i]&j)==j&&!(j&(j<<1))&&!(j&(j>>1)))
{
for(re int k=0;k<(1<<m);++k)//上一行状态
{
if(!(j&k))
{
(dp[i][j]+=dp[i-1][k])%=mod;
}
}
}
}
}
re int ans=0;
for(re int i=0;i<(1<<m);++i)
{
(ans+=dp[n][i])%=mod;
}
printf("%lld",ans);
return 0;
}
二、P2622 关灯问题II
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define inf 123456789000000
#define int long long
#define maxn 11
#define maxm 105
il int read()
{
re int x=0,k=1;re char c=getchar();
while(c<'0'||c>'9'){if(c=='-') k=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*k;
}
int n,m,dp[1<<maxn],a[maxm][maxn];
il int doit(int x,int t)
{
re int temp=0;
for(re int i=1;i<=n;++i)
{
if(a[t][i]==0) temp=(temp<<1)+(x%2);
else if(a[t][i]==1) temp<<=1;
else temp=(temp<<1)+1;
x>>=1;
}
return temp;
}
signed main()
{
n=read(),m=read();
for(re int i=1;i<=m;++i) for(re int j=1;j<=n;++j) a[i][j]=read();
for(re int i=0;i<(1<<n)-1;++i) dp[i]=inf;
for(re int i=(1<<n)-1;i>=0;--i)
{
if(dp[i]!=inf)
{
for(re int j=1;j<=m;++j)
{
re int temp=doit(i,j);
dp[temp]=min(dp[i]+1,dp[temp]);
}
}
}
dp[0]==inf?puts("-1"):printf("%lld",dp[0]);
return 0;
}
三、P3092 [USACO13NOV]没有找零No Change
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define int long long
using namespace std;
inline int read(){
int x=0,k=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') k=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*k;
}
int n,k,c[30],w[100005],dp[70000],ans=-1,sum[100005],tot,lo[30];
bool use[30],vis[100005];
inline void init()
{
k=read(),n=read();
for(int i=1;i<=k;i++)
{
c[i]=read();
tot+=c[i];
}
for(int i=1;i<=n;i++)
{
w[i]=read();
sum[i]=sum[i-1]+w[i];
}
lo[1]=1;
for(int i=2;i<=k;i++)
{
lo[i]=lo[i-1]<<1;
}
}
inline void work()
{
int ma=(1<<k);
for(int i=0;i<ma;i++)
{
for(int j=1;j<=k;j++)
{
if(i&lo[j])
{
int temp=upper_bound(sum+1,sum+n+1,sum[dp[i^lo[j]]]+c[j])-sum-1;
dp[i]=max(dp[i],temp);
}
}
}
for(int i=0;i<ma;i++)
{
if(dp[i]==n)
{
int cnt=0;
for(int j=1;j<=k;j++)
{
if(i&lo[j])
{
cnt+=c[j];
}
}
ans=max(ans,tot-cnt);
}
}
printf("%d",ans);
}
signed main()
{
init();
work();
return 0;
}
四、P2704 炮兵阵地
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
il int read()
{
re int x=0,k=1;re char c=getchar();
while(c<'0'||c>'9'){if(c=='-') k=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*k;
}
il int read2()
{
re char c=getchar();
while(c!='H'&&c!='P')c=getchar();
return c=='H'?1:0;
}
#define maxn 11
#define maxm 101
int n,m,sum[1<<maxn],s[maxm],dp[1<<maxn][1<<maxn][maxm],st[1<<maxn];
il int BSGS(int s)
{
re int ans=0;
while(s)
{
if(s&1) ++ans;
s>>=1;
}
return ans;
}
signed main()
{
//freopen("a.in","r",stdin),freopen("a.out","w",stdout);
n=read(),m=read();
for(re int i=1;i<=n;++i)
{
for(re int j=1;j<=m;++j)
{
s[i]=(s[i]<<1)+read2();
}
}
for(re int i=0;i<(1<<m);++i)
{
sum[i]=BSGS(i);
st[i]=(!(i&(i<<1))&&!(i&(i<<2)));
}
for(re int i=0;i<(1<<m);++i)
{
for(re int j=0;j<(1<<m);++j)
{
if(!(i&j)&&st[j]&&!(j&s[2])&&!(i&s[1])&&st[i])
{
dp[i][j][2]=sum[i]+sum[j];
}
}
}
for(re int i=3;i<=n;++i)
{
for(re int j=0;j<(1<<m);++j)
{
if(!(s[i]&j)&&st[j])
{
for(re int k=0;k<(1<<m);++k)
{
if(!(s[i-1]&k)&&!(j&k)&&st[k])
{
for(re int l=0;l<(1<<m);++l)
{
if(!(l&s[i-2])&&!(k&l)&&!(j&l)&&st[l])
{
dp[k][j][i]=max(dp[k][j][i],dp[l][k][i-1]+sum[j]);
}
}
}
}
}
}
}
re int ans=0;
for(re int i=0;i<(1<<m);++i)
{
for(re int j=0;j<(1<<m);++j)
{
ans=max(ans,dp[i][j][n]);
}
}
printf("%d",ans);
return 0;
}
五、P1896 [SCOI2005]互不侵犯
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 105
#define maxr 20
using namespace std;
inline int read(){
int x=0,k=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') k=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*k;
}
ll n,k,ans,cnt,s[maxn],num[maxn],dp[maxr][maxn][maxn];
inline void init()
{
n=read(),k=read();
for(int i=0;i<(1<<n);i++)
{
if(i&(i<<1))
{
continue;
}
s[++cnt]=i;
int t=0;
for(int j=0;j<n;j++)
{
if(i&(1<<j))
{
t++;
}
}
num[cnt]=t;
}
}
inline void work()
{
dp[0][1][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=cnt;j++)
{
for(int l=0;l<=k;l++)
{
if(l>=num[j])
{
for(int t=1;t<=cnt;t++)
{
if(!(s[t]&s[j])&&!(s[t]&(s[j]<<1))&&!((s[t]<<1)&s[j]))
{
dp[i][j][l]+=dp[i-1][t][l-num[j]];
}
}
}
}
}
}
for(int i=1;i<=cnt;i++)
{
ans+=dp[n][i][k];
}
cout<<ans;
}
int main()
{
init();
work();
return 0;
}
六、P3959 宝藏
#include<bits/stdc++.h>
using namespace std;
#define re register
#define il inline
#define debug printf("PassLine:%d\n", __LINE__)
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout);
#define maxn 15
#define maxm 1005
#define inf 123456789
il int read()
{
re int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
int n,m,a[maxn][maxn],dis[maxn],dp[1<<maxn],ans=inf;
il void dfs(int s)
{
for(re int i=1;i<=n;++i)
{
if(s&(1<<(i-1)))
{
for(re int j=1;j<=n;++j)
{
if(!(s&(1<<(j-1)))&&a[i][j]!=inf)
{
if(dp[1<<(j-1)|s]>dp[s]+dis[i]*a[i][j])
{
re int temp=dis[j];
dis[j]=dis[i]+1;
dp[1<<(j-1)|s]=dp[s]+dis[i]*a[i][j];
dfs(1<<(j-1)|s);
dis[j]=temp;
}
}
}
}
}
}
int main()
{
//file(a);
n=read(),m=read();
for(re int i=1;i<=n;++i) for(re int j=1;j<=n;++j) a[i][j]=inf;
for(re int i=1,u,v,w;i<=m;++i)
{
u=read(),v=read(),w=read();
a[u][v]=a[v][u]=min(w,a[u][v]);
}
for(re int i=1;i<=n;++i)
{
for(re int j=0;j<(1<<n);++j) dp[j]=inf;
for(re int j=1;j<=n;++j) dis[j]=inf;
dis[i]=1;
dp[1<<(i-1)]=0;
dfs(1<<(i-1));
ans=min(ans,dp[(1<<n)-1]);
}
printf("%d",ans);
return 0;
}
状压DP总结的更多相关文章
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
- [NOIP2016]愤怒的小鸟 D2 T3 状压DP
[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...
- 【BZOJ2073】[POI2004]PRZ 状压DP
[BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...
- bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)
数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...
- HDU 1074 Doing Homework (状压dp)
题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
- 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP
[BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...
- 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP
[BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...
- 【BZOJ1087】 [SCOI2005]互不侵犯King 状压DP
经典状压DP. f[i][j][k]=sum(f[i-1][j-cnt[k]][k]); cnt[i]放置情况为i时的国王数量 前I行放置情况为k时国王数量为J #include <iostre ...
随机推荐
- vue router 根据不同的id切换链接界面不刷新
我们一般使用vue的router时候会根据不同的id来切换界面,但是界面没有立刻刷新.下面我们讲下如何解决这个问题. html: <template> <div id="a ...
- PHP--高级算法--面试
数据结构和算法(转载) 原文地址: https://blog.csdn.net/s1070/article/details/51174725 1.使对象可以像数组一样进行foreach循环,要求属性 ...
- [转帖]Vim 编辑器底端 [noeol], [dos] 的含义
Vim 编辑器底端 [noeol], [dos] 的含义 2012年11月28日 23:13:04 strongwangjiawei 阅读数:15484 https://blog.csdn.net/s ...
- Day5-1 面向对象和面向过程
摘要: 类的定义 类的增删改查 对象的增删改查 对象的查找和绑定 面向对象和面向过程的区别: 1.面向过程就像是工厂的流水线,按部就班的有序的工作. 优点:把复杂的问题简单化 缺点:可扩展性差.一个步 ...
- Web移动端---iPhone X适配(底部栏黑横线)
一.相信大家有被iPhone X底部黑色横线支配的恐惧 上面我们可以看到,底部的导航栏被一条黑色横线所盖住,那么就很烦.下面我们可以开始进行适配环节 1.首先我们可以用 JS 判断手机环境是不是 iP ...
- 【转】使用 lsof 查找打开的文件
在 UNIX® 环境中,文件无处不在,这便产生了一句格言:“任何事物都是文件”.通过文件不仅仅可以访问常规数据,通常还可以访问网络连接和硬件.在有些情况下,当您使用 ls 请求目录清单时,将出现相 ...
- python学习笔记(10)--组合数据类型(序列类型)
序列是具有先后关系的一组数据,是一维元素向量,元素类型可以不同,类似数学元素序列,元素间由序号引导,通过下标访问序列的特定元素.序列类型是一个基类类型,字符串类型,元祖类型,列表类型都属于序列类型. ...
- css & clearfix & clear-fixed
css & clearfix & clear-fixed https://zzk.cnblogs.com/my/s/blogpost-p?Keywords=clearfix .grou ...
- python标准异常
什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行.一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当Python脚 ...
- Lodop获取客户端主网卡ip地址是0.0.0.0
LODOP技术手册的GET_SYSTEM_INFO篇,LODOP可以用语句获取到客户端很多信息,NetworkAdapter.1.IPAddress是主网卡IP地址,通常情况下是没问题的,不过如果当前 ...