题意:P放炮兵,前后左右不能放,求最多能放多少
思路:状态压缩dp
#include<cstdio>
#include<cstring>
#include<iostream>
#define max(a,b) (a>b?(a):(b))
using namespace std;
int sum[65],num[65];
int dp[105][65][65];
int map[105];
int cnt;
int check(int n)
{
if(n&(n<<1)) return 0;
if(n&(n<<2)) return 0;
return 1;
}
int count0(int n)
{
int count=0;
while(n>0)
{
if(n&1) count++;
n>>=1;
}
return count;
}
void findnum(int n)
{
cnt=0;
for(int i=0;i<(1<<n);i++)
{
if(check(i))
{
num[cnt]=i;
sum[cnt++]=count0(i);
}
}
}
int main()
{
int row,col;char ch;
cin>>row>>col;
memset(dp,-1,sizeof(dp));
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
{
cin>>ch;
if(ch=='H')
map[i]|=(1<<j);
}
findnum(col);
for(int i=0;i<cnt;i++)
if(!(map[0]&num[i]))
dp[0][0][i]=sum[i];
for(int r=1;r<row;r++)
{
for(int i=0;i<cnt;i++) //r
{
if(num[i]&map[r]) continue;
for(int j=0;j<cnt;j++) //r-1
{
if(num[i]&num[j]) continue;
for(int k=0;k<cnt;k++) //r-2
{
if(num[i]&num[k]) continue;
if(dp[r-1][k][j]==-1) continue;
dp[r][j][i]=max(dp[r][j][i],dp[r-1][k][j]+sum[i]);
}
}
}
}
int ans=0;
for(int i=0;i<cnt;i++)
for(int j=0;j<cnt;j++)
ans=max(ans,dp[row-1][i][j]);
cout<<ans<<endl;
return 0;
}