#loj 10170. 「一本通 5.4 例 1」骑士

看数据范围n<=10,所以不是搜索就是状压dp,又因为搜索会超时所以用dp

dp[i][k][j]表示现已经放到第i行,前面共有k个,这一行状态为j

so,dp[i][k][j]=dp[i-1][k-num[j]][t]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define low_bit(x) x&-x;
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
long long dp[][][];//dp[i][j][k]表示前i行放k个且第i行的状态为j
long long n,k,s[],num[];
long long cont(long long x)
{
long long c=;
while(x!=)
{
x-=low_bit(x);
c++;
}
return c;
}
int main()
{
n=read(),k=read();
long long ans=;
for(long long i=;i<(<<n)-;i++)
{
if((i&(i<<)))continue;
s[++ans]=i;
num[ans]=cont(i);
}
dp[][][]=;
// for(long long i=1;i<=ans;i++) cout<<s[i]<<" ";cout<<endl;
for(long long i=;i<=n;i++)
{
for(long long j=;j<=ans;j++)
{
for(long long kk=;kk<=k;kk++)
{
if(kk>=num[j])
{
for(long long t=;t<=ans;t++)
{
if(s[t]&s[j]) continue;
if(s[t]&(s[j]<<)) continue;
if(s[t]&(s[j]>>)) continue;
dp[i][j][kk]+=dp[i-][t][kk-num[j]];
// cout<<dp[i][j][k]<<endl;
}
}
}
}
}
long long sum=;
for(long long i=;i<=ans;i++) sum+=dp[n][i][k];
cout<<sum;
}

#loj 10171. 「一本通 5.4 例 2」牧场的安排

一道比较普通的状压dp,关键点就是输入时候怎么处理荒草

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mod 100000000
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
long long m,n;
//dp[i][j]表示第i行用第j个状态
//dp[i][j]+=dp[i-1][k]
long long dp[][];
long long ans[];//ans[i]表示第i行有ans[i]个状态
long long s[][];//s[i][j]表示第i行第j个状态
void init(long long h,long long t)
{
// cout<<t<<endl;
for(long long i=;i<=(<<n)-;i++)
{
if((i&(i<<))||(i&(i>>))||(i&t)) continue;
s[h][++ans[h]]=i;
}
return;
}
int main()
{
m=read(),n=read();
for(long long i=;i<=m;i++)
{
long long s=;
for(long long j=;j<=n;j++)
{
long long x=read();
s=(s<<)+-x;
}
init(i,s);
}
for(long long i=;i<=ans[];i++) dp[][i]=;
// for(long long i=1;i<=m;i++)
// {
// cout<<ans[i]<<endl;
// for(long long j=1;j<=ans[i];j++) cout<<s[i][j]<<" ";
// system("pause");
// }
//
for(long long i=;i<=m;i++)
{
for(long long j=;j<=ans[i];j++)
{
for(long long k=;k<=ans[i-];k++)
{
// cout<<i<<" "<<j<<" "<<k<<" "<<s[i][j]<<" "<<s[i-1][k]<<endl;
if(s[i][j]&s[i-][k]) continue;
// if((s[i][j]>>1)&s[i-1][k]) continue;
// if((s[i][j]<<1)&s[i-1][k]) continue;
dp[i][j]+=dp[i-][k]%mod;
}
}
}
long long sum=;
for(long long i=;i<=ans[m];i++) sum+=dp[m][i]%mod,sum%=mod;
cout<<sum%mod;
}

#loj 10172. 「一本通 5.4 练习 1」涂抹果酱

手打三进制运算即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mod 1000000
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
long long n,m,k,a[],dg[];
bool check(long long x)
{
memset(dg,,sizeof(dg));
long long ans=;
while(x!=)
{
dg[++ans]=x%;
x/=;
}
for(long long i=m;i>=;i--)
if(dg[i]==dg[i-]) return false;
return true;
}
long long s[],ans;
long long dg1[],dg2[];
void init()
{
ans=;
long long sry=;
for(long long i=;i<=m;i++) sry*=;
for(long long i=;i<=sry-;i++)
if(check(i))
s[++ans]=i;
return;
}
long long dp[][];
bool check2(long long x,long long y)
{
long long ans1=,ans2=;
memset(dg1,,sizeof(dg1));
memset(dg2,,sizeof(dg2));
while(x!=)
{
dg1[++ans1]=x%;
x/=;
}
while(y!=)
{
dg2[++ans2]=y%;
y/=;
}
for(long long i=m;i>=;i--)
if(dg1[i]==dg2[i]) return false;
return true;
}
long long cx(long long x)
{
for(long long i=;i<=ans;i++)
if(s[i]==x) return i;
}
long long book[][];
int main()
{
n=read(),m=read();
k=read();
for(long long i=;i<=m;i++)
{
a[i]=read();
a[i]-=;
}
long long kk=,sum=;
for(long long i=m;i>=;i--)
{
sum+=a[i]*kk;
kk*=;
}
if(check(sum)==false)
{
cout<<;
return ;
}
init();
for(long long i=;i<=ans;i++)
for(long long j=i;j<=ans;j++)
book[i][j]=book[j][i]=check2(s[i],s[j]);
memset(dp,,sizeof(dp));
for(long long i=;i<=ans;i++) dp[][i]=;
for(long long i=;i<=k;i++)
for(long long j=;j<=ans;j++)
for(long long k=;k<=ans;k++)
if(book[j][k])
{
dp[i][j]+=(dp[i-][k])%mod;
dp[i][j]%=mod;
// cout<<"行:"<<i<<" 状态:"<<j<<" dp[i][j]:"<<dp[i][j]<<endl;
}
long long xxxx=cx(sum);
long long p=dp[k][xxxx]%mod;
if(p==)
{
cout<<;
return ;
}
memset(dp,,sizeof(dp));
for(long long i=;i<=ans;i++) dp[n][i]=;
for(long long i=n-;i>=k;i--)
for(long long j=;j<=ans;j++)
for(long long k=;k<=ans;k++)
if(book[j][k])
{
dp[i][j]+=(dp[i+][k])%mod;
dp[i][j]%=mod;
} long long p1=dp[k][xxxx]%mod;
if(p1==)
{
cout<<;
return ;
}
cout<<(p1*p)%mod;
return ;
}

#loj 10173. 「一本通 5.4 练习 2」炮兵阵地

因为联系是由三行,所以dp数组存行数外还要开两位存这一位和上一位的状态

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define lowbit(x) x&-x
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int cont(int x)
{
int c=;
while(x!=)
{
x-=lowbit(x);
c++;
}
return c;
}
int ans[];
int s[][];
int n,m;
void init(int ha,int t)
{
for(int i=;i<=(<<m)-;i++)
{
if(i&(i<<)) continue;
if(i&(i<<)) continue;
if(i&(i>>)) continue;
if(i&(i>>)) continue;
if(i&t) continue;
s[ha][++ans[ha]]=i;
}
return;
}
int dp[][][];
int main()
{
n=read(),m=read();
for(int i=;i<=n;i++)
{
char str;
int t=;
for(int j=;j<=m;j++)
{
cin>>str;
if(str=='P') t=(t<<);
else if(str=='H') t=(t<<)+;
}
init(i,t);
}
if(n==)
{
cout<<ans[];
return ;
}
for(int i=;i<=ans[];i++)
{
for(int j=;j<=ans[];j++)
{
int s1=s[][i],s2=s[][j];
if(s1&s2) continue;
dp[][i][j]=max(dp[][i][j],cont(s1)+cont(s2));
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=ans[i];j++)
{
for(int k=;k<=ans[i-];k++)
{
if(s[i][j]&s[i-][k]) continue;
for(int t=;t<=ans[i-];t++)
{
int s1=s[i][j],s2=s[i-][k],s3=s[i-][t];
if(s1&s2) continue;
if(s1&s3) continue;
if(s2&s3) continue;
dp[i%][j][k]=max(dp[i%][j][k],dp[(i-)%][k][t]+cont(s1)); }
}
}
}
int sum=;
for(int i=;i<=ans[n];i++)
for(int j=;j<=ans[n-];j++)
{
if(s[n][i]&s[n-][j]) continue;
sum=max(sum,dp[n%][i][j]);
}
cout<<sum;
}
/*
5 4
PHPP
PPHH
PPPP
PHPP
PHHP
*/

#loj 10174. 「一本通 5.4 练习 3」动物园

这题的关键点就在小朋友只能看到5个数字

所以只需要状压这5个数字就好了

其实不需要断环为链

因为你可以每次先假设一种状态关系到0(其实是n),1,2,3,4

最后只需要输出关于n的这种最大状态

每次看一下需不需要放

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
int n,c;
int e,f,l;
int g[][],dp[][];
int main()
{
n=read(),c=read();
for(int p=;p<=c;p++)
{
e=read(),f=read(),l=read();
int scared=;
for(int i=;i<=f;i++)
{
int x=read();
x=(x-e+n)%n;
scared|=(<<x);
}
int happy=;
for(int i=;i<=l;i++)
{
int x=read();
x=(x-e+n)%n;
happy|=(<<x);
}
int sry=;
for(int i=;i<=;i++)
{
if((i&happy)||((sry^i)&scared))
{
g[e][i]++;
// cout<<i<<endl;
}
}
}
int ans=;
for(int s=;s<=;s++)
{
for(int j=;j<=;j++) dp[][j]=-(<<-);
dp[][s<<]=dp[][s<<|]=;
for(int i=;i<=n;i++)
for(int ss=;ss<=;ss++)
dp[i][ss]=max(dp[i-][(ss&)<<],dp[i-][(ss&)<<|])+g[i][ss];
ans=max(ans,max(dp[n][s<<|],dp[n][s<<]));
}
cout<<ans;
}

YBT 5.4 状态压缩动态规划的更多相关文章

  1. BZOJ_4197_[Noi2015]寿司晚宴_状态压缩动态规划

    BZOJ_4197_[Noi2015]寿司晚宴_状态压缩动态规划 Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被 ...

  2. 状态压缩动态规划 状压DP

    总述 状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式 很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍 有了状态,DP就比 ...

  3. 状态压缩动态规划(状压DP)详解

    0 引子 不要999,也不要888,只要288,只要288,状压DP带回家.你买不了上当,买不了欺骗.它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味! 在计算机 ...

  4. poj 3254(状态压缩+动态规划)

    http://poj.org/problem?id=3254 题意:有一个n*m的农场(01矩阵),其中1表示种了草可以放牛,0表示没种草不能放牛,并且如果某个地方放了牛,它的上下左右四个方向都不能放 ...

  5. 【学术篇】状态压缩动态规划——POJ3254/洛谷1879 玉米田Corn Field

    我要开状压dp的坑了..直播从入门到放弃系列.. 那就先拿一道状压dp的水题练练手吧.. 然后就找到了这一道..这道题使我清醒地认识到阻碍我的不是算法,而是视力= = 传送门: poj:http:// ...

  6. BZOJ1087 [SCOI2005]互不侵犯King 状态压缩动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1087 题意概括 在n*n的棋盘上面放k个国王,使得他们互相无法攻击,问有多少种摆法. 题解 dp[ ...

  7. BZOJ1076 [SCOI2008]奖励关 概率 状态压缩动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1076 题意概括 有n个东西,k次扔出来.每次等概率扔出其中一个. 你可以拿这个东西,但是有条件,得 ...

  8. CODEVS_2800 送外卖 状态压缩+动态规划

    原题链接:http://codevs.cn/problem/2800/ 题目描述 Description 有一个送外卖的,他手上有n份订单,他要把n份东西,分别送达n个不同的客户的手上.n个不同的客户 ...

  9. Vijos 1921 严厉的班长 【状态压缩动态规划】

    严厉的班长 描述 木姑娘在班级里面是班长.虽然是副班长,却有着比正班长更高的威信,并深受小朋友们的爱戴. 每天眼保健操时间,木姑娘都要监督所有小朋友认真做眼保健操.整个过程被描述为n个时间段,第i个时 ...

随机推荐

  1. 180601-MySql性能监控工具MyTop

    文章链接:https://blog.hhui.top/hexblog/2018/06/01/180601-MySql性能监控工具MyTop/ mysql 性能监控小工具之 mytop 参考: How ...

  2. HTTP请求中get和post的区别是什么

    GET和POST是Http请求中最常用的两种请求方法 首先介绍GET与POST的差异: (1)GET请求资源数据,POST向服务器传递需要处理的数据 (2)GET传递数据大小不超过2kb,POST没有 ...

  3. Struts2(八.添加用户多张照片实现文件上传功能)

    1.modify.jsp 在modify.jsp修改用户信息页面实现文件上传,添加用户照片的功能 如果是文件上传,method必须是post,必须指定enctype <form method=& ...

  4. LeetCode 96——不同的二叉搜索树

    1. 题目 2. 解答 以 \(1, 2, \cdots, n\) 构建二叉搜索树,其中,任意数字都可以作为根节点来构建二叉搜索树.当我们将某一个数字作为根节点后,其左边数据将构建为左子树,右边数据将 ...

  5. 四:HDFS Snapshots

    1.介绍 HDFS快照保存某个时间点的文件系统快照,可以是部分的文件系统,也可以是全部的文件系统.快照用来做数据备份和灾备.有以下特点: 1.快照几乎是实时瞬间完成的 2.只有在做快照时文件系统有修改 ...

  6. [C++] OOP - Virtual Functions and Abstract Base Classes

    Ordinarily, if we do not use a function, we do not need to supply a definition of the function. Howe ...

  7. 【转】Hbuilder MUI 页面刷新及页面传值问题

    文章来源:http://www.111cn.net/sys/CentOS/67213.htm 一.页面刷新问题 1.父页面A跳转到子页面B,B页面修改数据后再跳回A页面,刷新A页面数据 (1).父页面 ...

  8. 百度编辑器ueditor的图片地址修正

    我用的百度编辑器为1.4.2的,相对于现在这个时间来说是比较新的.之前去的1.3版的,后来更新到1.4之后出现路径问题.因为今天晚上出现特别奇怪的问题,所以特地又整了一遍,发现这玩意还是得自己弄通了好 ...

  9. python中装饰器的原理以及实现,

    python版本 3.6 1.python的装饰器说白了就是闭包函数的一种应用场景,在运用的时候我们遵循 #开放封闭原则:对修改封闭,对拓展开放 2.什么是装饰器 #装饰他人的器具,本身可以是任意可调 ...

  10. MONyog-数据库性能监控工具

    一.安装步骤 较为简单,网上可以搜索到,此处不做详细说明. 二.使用图解 此处介绍监控数据库连接量.并发量.吞吐量.响应时间等功能 1.设置连接需要监控的数据库 打开:http://127.0.0.1 ...