题意是汉语.
解析:可以发现,对于每一行放大炮的状态,只与它上面一行和上上一行的状态有关,每一行用状态压缩的表示方法,0表示不放大炮,1表示放大炮,同样的,先要满足硬件条件,即有的地方不能放大炮,然后就是每一行中不能有两个1的距离小于2(保证横着不互相攻击),这些要预先处理一下。然后就是状态表示和转移的问题了,因为是和前两行的状态有关,所以要开个三维的数组来表示状态,当前行的状态可由前两行的状态转移而来。即如果当前行的状态符合前两行的约束条件(不和前两行的大炮互相攻击),则当前行的最大值就是上一个状态的值加上当前状态中1的个数(当前行放大炮的个数)
状态表示dp[i][j][k] 表示第i行状态为j,第i-1状态为k时的最大炮兵个数。
状态转移方程dp[i][j][k] =max(dp[i][j][k],dp[i-1][j][h]+num[j]); num[j]为t状态中1的个数 .
//C++ 1868K 282MS
#include <stdio.h>
#include <string.h>
#define MAX(A,B) ((A)>(B)?(A):(B))
#define V 65 // V 可搜索得出,当M=10时,共有60种情况
int dp[105][V][V] ;
int nState ;
int state[V] , num[V] ;
void
Init ( int const m )
{
int k ;
k = 1 << m ;
nState = 0 ;
for ( int i = 0 ; i < k ; i ++ )
{
if ( 0 == ( i &( i << 1 ) ) && 0 == ( i & ( i << 2 ) ) )
{
state[nState] = i ;
num[nState] = 0 ;
int j = i ;
while ( j )
{
num[nState] += j % 2 ;
j >>= 1 ;
}
nState ++ ;
}
}
return ;
}
int
main ( )
{
int n , m ; //n 代表行,m代表列
int row[105] ;
char str[15] ;
while ( EOF != scanf ("%d%d" , & n , & m ) )
{
Init ( m ) ;
for ( int i = 0 ; i < n ; i ++ )
{
row[i] = 0 ;
scanf ("%s" , str ) ;
for ( int j = 0 ; j < m ; j ++ )
{
if ( 'P' == str[j] )
{
row[i] += 1 << j ;
}
}
}
memset ( dp , 0 , sizeof ( dp ) ) ;
//计算dp[0]
for ( int j = 0 ; j < nState ; j ++ )
{
if ( ( state[j] & row[0] ) != state[j] )
{
continue ;
}
/*
for ( int k = 0 ; k < nState ; k ++ )
{
dp[0][j][k] = num[j] ;
}
*/
dp[0][j][0] = num[j] ;
}
//计算dp[1]
/*
if ( n > 1 )
{
for ( int j = 0 ; j < nState ; j ++ )
{
if ( ( state[j] & row[1] ) != state[j] )
{
continue ;
}
for ( int k = 0 ; k < nState ; k ++ )
{
if ( 0 == ( state[j] & state[k] ) )
{
dp[1][j][k] = dp[0][k][0] + num[j] ;
}
}
}
}
*/
//计算dp[1~n-1]
for ( int i = 1 ; i < n ; i ++ )
{
for ( int j = 0 ; j < nState ; j ++ )
{
if( ( row[i] & state[j] ) != state[j] ) //如果状态j和第i行的地形冲突,注意,有state[j] = 0 这种情况
{
continue ;
}
for ( int k = 0 ; k < nState ; k ++ )
{
if ( state[j] & state[k] ) //如果第i行状态j和第i-1行状态k冲突
{
continue ;
}
for ( int h = 0 ; h < nState ; h ++ )
{
if ( state[j] & state[h] ) //如果第i行状态j和第i-2行状态h冲突
{
continue ;
}
dp[i][j][k] = MAX ( dp[i][j][k] , dp[i-1][k][h] + num[j] ) ;
}
}
}
}
int ans ;
ans = 0 ;
for ( int j = 0 ; j < nState ; j ++ )
{
for ( int k = 0 ; k < nState ; k ++ )
{
ans = MAX ( ans , dp[n-1][j][k] ) ;
}
}
printf ("%d\n" , ans ) ;
}
return 0 ;
}