题目链接:http://poj.org/problem?id=1185
题目大意,在保证不互相攻击的条件下放炮兵,开始题意理解有误,写了很久都没有写出来,这是一个比较好的状态压缩dp,先将一行的所有可能状态搜出来,再枚举所有可能状态逐行dp,这个题要枚举前两行状态,当然也可以用3进制。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define Max 110
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int n,m,tmp;
//vector<int>v[1<<11];
//vector<int>vt;
int vt[100],num;
int flag[1<<11];
char mp[110][11];
int dp[100][100][2];
int i,st1,st2,st3;
void dfs(int pos,int s)
{
int temp;
if(pos<m)
{
temp=s+(1<<pos);
flag[temp]=1;
if(pos+3<m)
dfs(pos+3,temp);
}
if(pos+1<m)
dfs(pos+1,s);
}
int main()
{
int j,k,l,g,cnt;
// freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
scanf("%s",mp[i]);
num=0;
dfs(0,0);
flag[0]=1;
for(i=0;i<(1<<10);i++)
{
if(flag[i])
{
vt[num++]=i;
}
}
tmp=0;
dp[0][0][0]=0;
for(i=0;i<n;i++)
{
for(j=0;j<num;j++)
{
for(k=0;k<num;k++)
{
dp[j][k][1-tmp]=-1;
}
}
for(j=0;j<num;j++)
{
st1=vt[j];
int rec=0;cnt=0;
for( g=0;g<m;g++)
{
if((st1&(1<<g))!=0&&mp[i][g]=='H')
{
rec=1;
break;
}
if((st1&(1<<g))!=0)
cnt++;
}
if(rec)continue;
for(k=0;k<num;k++)
{
st2=vt[k];
for(l=0;l<num;l++)
{
st3=vt[l];
if(dp[k][l][tmp]!=-1)
{
if((st1&st2)==0&&(st1&st3)==0&&(st2&st3)==0)
{
dp[j][k][1-tmp]=max(dp[j][k][1-tmp],dp[k][l][tmp]+cnt);
}
}
}
}
}
tmp=1-tmp;
}
int ans=0;
for(j=0;j<num;j++)
{
for(k=0;k<num;k++)
{
ans=max(dp[j][k][tmp],ans);
}
}
printf("%d\n",ans);
}