POJ1185 炮兵阵地(压缩DP)

来源:互联网 发布:linux 编译安装php7 编辑:程序博客网 时间:2024/05/17 21:54
一道水题又调了一晚上。。。发现每次的错误都让人很蛋疼。。。

这题和POJ3254类似,只不过相互影响的状态多了一行,dp数组就要增加一维,记录的总合法情况数变成了最大合法情况,还是很水的一道题。。。

dp[i][j][k]表示第i行 ,本行状态为val[j],上一行状态为val[k]的最大炮的个数,一开始写成了dp[i][val[j]][val[k]]将状态无形中扩大了,一直在RE和WA中徘徊,后来发现了数组越界的问题

 

#include <cstdio>#include <cstring>#define max(a,b) (a>b?a:b)int map[120];int n,m;char tmp[25];int dp[120][65][65];//需要三维,二维时只能保存局部最优解,貌似不是很可行。。// 行数 本行状态 上一行状态;int val[65],num;int mm;bool valid (int x){    return !(((x<<1)&x) || ((x<<2)&x));}int getones(int x){    int res=0;    for ( ; x ; x>>=1)if(x&1)res++;    return res;}bool checkonmap(int row , int x){    //printf("%o %o\n",map[row],x);    return !(map[row]&x);}void init(){    num=0;    memset (val , 0 , sizeof(val));    for (int i=0 ; i<1024 ; ++i)    {        if(valid(i)) val[num++]=i;    }    //printf("%d %d\n",val[num-1],num);}void debug (){    for (int i=0 ; i<n ; ++i)    {        for (int j=0 ; val[j]<mm ; ++j)        {            for (int p=0 ; val[p]<mm ; ++p)            //printf("i=%dj=%dp=%d %d  ",i,j,p,dp[i][j][p]);            //if(checkonmap(i,val[j]))            printf("%d ",dp[i][val[j]][val[p]]);            printf("\n");        }        puts("");    }}int main(){    init();    while (~scanf("%d%d",&n,&m))    {        memset (map , 0 , sizeof(map));        mm=1<<m;        int ans=0;        for (int i=0 ; i<n ; ++i)        {            scanf("%s",tmp);            for (int j=0 ; j<m ; ++j)            {                if(tmp[j]=='H')map[i]|=(1<<j);            }            for (int j=m ; j<13 ; ++j)                map[i]|=1<<j;        }        memset (dp , 0 ,sizeof(dp));        for (int i=0 ; i<n ; ++i)        {            for (int j=0 ; val[j]<mm ; ++j)            {                if(i==0)                {                    if(!checkonmap(i,val[j]))continue;                    dp[i][j][0]+=getones(val[j]);                    continue ;                }                for (int k=0 ; val[k]<mm ; ++k)                {                    if(i==1)                    {                        if(!checkonmap(i,val[j]))continue;                        if(checkonmap(i-1,val[k]))                        if(!(val[k]&val[j]))                            dp[i][j][k]=                                max(dp[i][j][k],dp[i-1][k][0]+getones(val[j]));                        continue;                    }                    //if(!checkonmap(i,val[k]))continue;                    for (int p=0 ; val[p]<mm ; ++p)                    {                        if(checkonmap(i,val[j]))                        if(checkonmap(i-1,val[k]))                        if(checkonmap(i-2,val[p]))                        if(!(val[k]&val[p]))                        if(!(val[k]&val[j]))                        if(!(val[j]&val[p]))                            dp[i][j][k]=                                max(dp[i-1][k][p]+getones(val[j]),dp[i][j][k]);                    }                }            }        }        for (int i=0 ; val[i]<mm ; ++i)        {            for (int j=0 ; val[j]<mm ; ++j)            {                if(!checkonmap(n-1,val[i]))continue;                if(!checkonmap(n-2,val[j]))continue;                ans=max(ans,dp[n-1][i][j]);                //printf("%o %o  %d\n",val[i] ,val[j],dp[n-1][val[i]][val[j]]);            }        }        //debug();        printf("%d\n",ans);    }    return 0;}