POJ 1185 炮兵阵地
一般这类题目列会很小10左右,我们需要枚举所有行,对于当前行,其放炮的位置只与上一行和上上行有关,我们记当前行状态和上一行状态便可转移了,dp数组开3维即可。
在枚举每一行放炮兵的方法时,可以预处理方便获得所有可能放法。具体细节见代码。总体复杂度O(Row*70*70*70),70是预处理得到的每一行最多放法。打表很容易看出来。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char map[105][12];
int n,m,hmap[105],shell[70],permutation[70],all,dp[2][70][70];
void init(){
int i,k;
all=0;
memset(shell,0,sizeof(shell));
for(i=0;i<1<<m;i++){
k=i;
if( (i&(k>>1)) || (i&(k>>2)) )
continue;
shell[all]+=k%2;
k/=2;
while(k!=0){
shell[all]+=k%2;
k/=2;
}
permutation[all++]=i;
}
}
void dps(){
int row,i,j,k,h,max=0;
memset(dp,0,sizeof(dp));
row=0;
for(i=0;i<n;i++){
for(j=0;j<all;j++){
if(permutation[j]&hmap[i])
continue;
if(i==0){
dp[row][j][0]=shell[j];
}
else if(i==1){
for(k=0;k<all;k++){
if(permutation[k]&hmap[i-1]){
continue;
}
if(permutation[k]&permutation[j]){
continue;
}
if(dp[row][j][k]<dp[(row+1)%2][k][0]+shell[j])
dp[row][j][k]=dp[(row+1)%2][k][0]+shell[j];
}
}
else{
for(k=0;k<all;k++){
if(permutation[k]&hmap[i-1]){
continue;
}
if(permutation[k]&permutation[j]){
continue;
}
for(h=0;h<all;h++){
if(permutation[h]&hmap[i-2]){
continue;
}
if(permutation[h]&permutation[j]){
continue;
}
if(permutation[h]&permutation[j]){
continue;
}
if(dp[row][j][k]<dp[(row+1)%2][k][h]+shell[j])
dp[row][j][k]=dp[(row+1)%2][k][h]+shell[j];
}
}
}
}
row=(row+1)%2;
}
for(i=0;i<all;i++){
for(j=0;j<all;j++){
if(max<dp[(row+1)%2][i][j])
max=dp[(row+1)%2][i][j];
}
}
printf("%d\n",max);
}
int main()
{
int i,j,k;
scanf("%d %d",&n,&m);
memset(hmap,0,sizeof(hmap));
for(i=0;i<n;i++)
scanf("%s",map[i]);
for(i=0;i<n;i++){
for(j=