#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. Appium(Python)API

    1.创建新的会话desired_caps = desired_caps = {  'platformName': 'Android',  'platformVersion': '7.0',  'dev ...

  2. Selenium(Python)调用pywin32上传图片

    import unittestfrom time import sleep import osfrom selenium import webdriverimport win32apiimport w ...

  3. 给大家推荐:五个Python小项目,Github上的人气很高的

    1.深度学习框架 Pytorch https://github.com/pytorch/pytorch PyTorch 是一个 Torch7 团队开源的 Python 优先的深度学习框架,提供两个高级 ...

  4. GRU-CTC中文语音识别

    目录 基于keras的中文语音识别 音频文件特征提取 文本数据处理 数据格式处理 构建模型 模型训练及解码 aishell数据转化 该项目github地址 基于keras的中文语音识别 该项目实现了G ...

  5. facebook演讲

    任何为了更大愿景工作的人,可能会被称为疯子,即使你最终获得成功. 任何为了复杂问题工作的人,都会因为不能全面了解挑战而被指责,即使你不可能事先了解一切. 任何抓住主动权先行一步的人,都会因为步子太快而 ...

  6. eos智能合约开发最佳实践

    安全问题 1.可能的错误 智能合约终止 限制转账限额 限制速率 有效途径来进行bug修复和提升 2.谨慎发布智能合约 对智能合约进行彻底的测试 并在任何新的攻击手法被发现后及时制止 赏金计划和审计合约 ...

  7. 第八章 IO库

    8.1&&8.2 #include <iostream> #include <vector> #include <string> using nam ...

  8. 软工2017第四周作业结对编程——个人psp

    29.22 --9.26本周例行报告 1.PSP(personal software process )个人软件过程. 类型 任务 预计时间 开始时间                结束时间 中断时间 ...

  9. Java接口与继承作业

    为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来? 因为子类继承了父类,那么就默认的含有父类的公共成员方法和公共成员变量,这些方法和变量在子类里不再重复声明.如果 ...

  10. 有关c#的学习笔记整理与心得

    [ 塔 · 第 一 条 约 定 ] 整理c#:Array Arraylist List Hashtable Dictionary Stack Queue等 Array 的容量是固定的,而 ArrayL ...