POJ1185 炮兵阵地

来源:互联网 发布:柏拉图网络专业建网站 编辑:程序博客网 时间:2024/04/28 05:24

这道题用DP做有两种解法,一是三进制表示,我认为这种应该是比较理想的,但是比较难写。

另一种就是二进制,不过需要注意的是,每一行的状态最多只有60种,所以60*60*60*100加上一些剪枝勉强可以过= =

用dp[i][j][k]表示第i行,上一行的状态是j,这一行的状态是k。则转移到下一行时有,dp[i+1][k][l]=max(dp[i+1][k][l], dp[i][j][k]+popcount[l])

注意不要用map,vector什么的,很容易就超时了= =


#include <cstdio>#include <cstring>int n,m,tot,ans;char mmp[15];int mp[105];int dp[105][65][65];int dic[65];int popcount[65];inline int max(int a, int b) {return a>b?a:b;}int main(){    while (scanf("%d%d",&n,&m)==2)    {        tot=0;        for (int i=0;i<(1<<m);i++)        {            if ((i&(i<<1)) || (i&(i<<2))) continue;            int tmp=i; popcount[tot]=0;            while (tmp) {popcount[tot]+=(tmp&1); tmp>>=1;}            dic[tot]=i; tot++;        }        for (int i=1;i<=n;i++)        {            scanf("%s",mmp);            mp[i]=0;            for (int j=0;j<m;j++) mp[i]=mp[i]<<1|(mmp[j]=='H');        }        memset(dp,-1,sizeof(dp));        for (int i=0;i<tot;i++)        {            if (dic[i]&mp[1]) continue;            dp[1][0][i]=popcount[i];        }        for (int i=1;i<=n;i++)            for (int j=0;j<tot;j++)                for (int k=0;k<tot;k++)                {                    if (dic[j]&dic[k]) continue;                    int x=mp[i]|dic[j]|dic[k];                    for (int l=0;l<tot;l++)                    {                        if (dic[l]&x) continue;                        if (dp[i-1][j][k]==-1) continue;                        dp[i][k][l]=max(dp[i][k][l],dp[i-1][j][k]+popcount[l]);                        //printf("%d %d %d %d\n",i,dic[k],dic[l],dp[i][k][l]);                    }                }        ans=0;        for (int i=0;i<tot;i++)            for (int j=0;j<tot;j++)                ans=max(ans,dp[n][i][j]);        printf("%d\n",ans);    }    return 0;}


原创粉丝点击