这三道题目异曲同工,如果不能完成,那么看懂一道题的题解后,自己实现剩余两道应该没有问题
顺便附一个状压dp的视频讲解
点此进入
POJ-3254 Corn Fields
#include<cstdio>
#include<algorithm>
#include<cstring>
const int MOD=100000000,STATE=1<<12,ROW=12+1;
int St[STATE+1],Bare[ROW],dp[ROW][STATE];
int main(){
int k=0;
for(int i=0;i<STATE;++i)if(!(i&(i<<1)))St[k++]=i;//每行所有的合法状态
St[k]=STATE;
int m,n,t;
scanf("%d%d",&m,&n);
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
scanf("%d",&t);Bare[i]=(Bare[i]<<1)|(!t);
}
}
int s=1<<n;
for(int i=0;St[i]<s;++i)if(!(Bare[0]&St[i]))dp[0][i]=1;
for(int r=1;r<m;++r){
for(int i=0;St[i]<s;++i){
if(!(Bare[r-1]&St[i])){
for(int ri=0;St[ri]<s;++ri){
if(!(Bare[r]&St[ri]) && !(St[i]&St[ri])){
dp[r][ri]=(dp[r][ri]+dp[r-1][i])%MOD;
}
}
}
}
}
int ans=dp[m-1][0];
for(int i=1;St[i]<s;++i){
ans=(ans+dp[m-1][i])%MOD;
}
printf("%d\n",ans);
return 0;
} HDU-4539 排兵布阵
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
const int STATE=1<<10;
int dp[101][180][180],num[1<<10+1],St[201],marsh[201];
int get_bit1(int x){
int nx=0;
while(x){
if(x%2)nx++;
x/=2;
}
return nx;
}
bool ok(int x,int y){
if(x & y<<1 || x<<1 & y) return 0;
return 1;
}
int main(){
int m,n,k=0;
for(int i=0;i<STATE;++i){
if(!(i&(i<<2)))St[k++]=i;
num[i]=get_bit1(i);
}
St[k]=STATE;
//std::cout<<k<<"\n";
while(scanf("%d%d",&n,&m)==2&&n){
memset(dp,-1,sizeof(dp));
int t;
for(int i=0;i<n;++i){
marsh[i]=0;
for(int j=0;j<m;++j){
scanf("%d",&t);marsh[i]=(marsh[i]<<1)|(!t);
}
}
int s=1<<m;
for(int i=0;St[i]<s;++i){
if(!(marsh[0]&St[i]))
for(int j=0;St[j]<s;++j){
dp[0][i][j]=num[St[i]];
}
}
for(int i=0;St[i]<s;++i){
if(!(marsh[1]&St[i]))
for(int j=0;St[j]<s;++j){
if(ok(St[i],St[j]) && !(marsh[0]&St[j]))
for(int kk=0;St[kk]<s;++kk){
if(dp[0][j][kk]!=-1)dp[1][i][j]=std::max(dp[0][j][kk]+num[St[i]],dp[1][i][j]);
}
}
}
for(int r=2;r<n;++r){
for(int i=0;St[i]<s;++i){
if(!(St[i]&marsh[r-2])){
for(int ri1=0;St[ri1]<s;++ri1){
if(!(St[ri1]&marsh[r-1])){
for(int ri=0;St[ri]<s;++ri){
if(!(St[ri]&marsh[r]) && (!(St[i]&St[ri])) && ok(St[ri1],St[ri]) ){
if(dp[r-1][ri1][i]!=-1)
dp[r][ri][ri1]=std::max(dp[r][ri][ri1],dp[r-1][ri1][i]+num[St[ri]]);
}
}
}
}
}
}
}
int ans=0;
for(int i=0;St[i]<s;++i)
{
for(int j=0;St[j]<s;++j)
ans = std::max(ans,dp[n-1][i][j]);
}
printf("%d\n",ans);
}
return 0;
} POJ-1185 炮兵布阵
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int STATE=1<<11,ROW=101;
inline int get_bit1(int x){
int nx=0;
while(x){
if(x%2)nx++;
x/=2;
}
return nx;
}
int st[101],n,m,marsh[101],dp[ROW][101][101],ST,num[STATE];
char tab[ROW][10+1];
inline void init(){
for(int i=0;i<n;++i){
marsh[i]=0;
for(int j=0;j<m;++j)
if(tab[i][j]!='P')marsh[i]=(marsh[i]<<1)|1;
else marsh[i]=marsh[i]<<1;
}
memset(dp,-1,sizeof(dp));
ST=1<<m;
for(int i=0;st[i]<ST;++i){
if(!(marsh[0]&st[i]))
for(int j=0;st[j]<ST;++j){
dp[0][i][j]=num[st[i]];
}
}
}
int dfs(int row,int r1,int r2){
int &d=dp[row][r1][r2];
if(row==0||d!=-1){
return d;
}
d=0;
if(row==1){
for(int r3=0;st[r3]<ST;++r3){
if(!(st[r1]&st[r2]) && dp[row-1][r2][r3]!=-1 &&!(marsh[row]&st[r1])){
d=std::max(d,dfs(row-1,r2,r3)+num[st[r1]]);
}
}
return d;
}
if(!(marsh[row-1]&st[r2]) && !(marsh[row]&st[r1])){
for(int r3=0;st[r3]<ST;++r3){
if(!(marsh[row-2]&st[r3])){
if(!(st[r1]&st[r2]) && !(st[r2]&st[r3]) && !(st[r1]&st[r3])){
d=std::max(d,dfs(row-1,r2,r3)+num[st[r1]]);
}
}
}
}
return d;
}
int main(){
int k=0;
for(int i=0;i<STATE;++i){
if(!((i<<2)&i) && !((i<<1)&i))st[k++]=i;
num[i]=get_bit1(i);
}st[k]=STATE;
while(scanf("%d%d",&n,&m)==2&&n){
for(int i=0;i<n;++i)scanf("%s",tab[i]);
init();
int ans=0;
for(int i=0;st[i]<ST;++i){
for(int j=0;st[j]<ST;++j){
ans=std::max(ans,dfs(n-1,i,j));
}
}
printf("%d\n",ans);
}
return 0;
} 
京公网安备 11010502036488号