POJ 1185
经典的状态压缩DP题了。做了前面两题,就不感觉难了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int stack[1<<10],cst;
int dp[2][1<<10][1<<10];
int G[105],tot[1<<10];
char str[15];
int n,m;
void Init(){
int alt=(1<<10);
memset(tot,0,sizeof(tot));
for(int i=0;i<alt;i++){
int st=1;
for(int j=0;j<10;j++){
st=1<<j;
if(st&i) tot[i]++;
}
// cout<<tot[i]<<endl;
}
}
void predo(){
cst=0;
int alt=1<<m;
int l1,l2,r1,r2;
for(int i=0;i<alt;i++){
bool flag=true;
for(int j=0;j<m;j++){
int st=1<<j;
if(st&i){
l1=st<<1,l2=st<<2;
r1=st>>1,r2=st>>2;
if(l1&i){flag=false; break;}
if(l2&i){flag=false; break;}
if(r1&i){flag=false; break;}
if(r2&i){flag=false; break;}
}
}
if(flag) stack[cst++]=i;
}
// cout<<cst<<endl;
}
void slove(){
memset(dp,-1,sizeof(dp));
int cur=0,next=1;
dp[cur][0][0]=0;
for(int i=0;i<n;i++){
for(int j=0;j<cst;j++){
for(int k=0;k<cst;k++){
if(dp[cur][j][k]==-1) continue;
for(int p=0;p<cst;p++){
// cout<<"YES"<<endl;
if((stack[p]&G[i+1])!=stack[p]) continue;
if(i>=1)
if(stack[p]&stack[j]) continue;
if(i>=2) if(stack[p]&stack[k]) continue;
dp[next][p][j]=max(dp[next][p][j],dp[cur][j][k]+tot[stack[p]]);
}
}
}
memset(dp[cur],-1,sizeof(dp[cur]));
swap(cur,next);
}
int ans=0;
for(int i=0;i<cst;i++){
for(int j=0;j<cst;j++)
ans=max(ans,dp[cur][i][j]);
}
printf("%d\n",ans);
}
int main(){
Init();
while(scanf("%d%d",&n,&m)!=EOF){
predo();
for(int i=1;i<=n;i++){
scanf("%s",str);
G[i]=0;
for(int j=0;j<m;j++){
G[i]<<=1;
if(str[j]=='P') G[i]|=1;
}
}
slove();
}
return 0;
}

浙公网安备 33010602011771号