POJ1185 炮兵阵地 (状态压缩DP)

原创 2015年11月18日 22:42:52

题目点我点我点我
题目大意:简单不多说

思路:先全列出所有可行的状态,放炮兵就为1,不放就为0,这时先不考虑地形,把可行状态列出来后,再与地形匹配,山地H为1,平原p为0,这样两者以二进制匹配得数为0则匹配成功。
然后第i行(i>2)只由第i-1行的状态和第i-2行的状态决定,dp[i][j][k]代表第i行的状态为j,第i-1行状态为k,所以有状态转移方程 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+soldier[j]),soldier[j]表示j状态下炮兵数量。
另外要初始化第一行第二行的状态,详情见代码。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define maxn 60  //状态数,另用程序跑跑记录10列是有60种符合的状态
int state[maxn],soldier[maxn];    //state记录可行状态,soldier记录士兵数
int top,N,M;   //top记录最多的可行状态数
int place[102],dp[102][maxn][maxn];  //place记录输入地形
char s[11];

void init()  //初始化所有可行状态,1代表放士兵,0则无
{
    top=0;
    for(int i=0;i<1<<10;i++)
    {
        if(((i<<1)&i)||((i<<2)&i))   //左边两格是否有其他炮兵
            continue;
        int temp=i;
        while(temp)
        {
            if(temp&1)soldier[top]++;   //每一个1炮兵就多一个
            temp>>=1;              
        }
        state[top++]=i;    //记录这个状态
    }

}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    init();
    while(~scanf("%d%d",&N,&M))
    {
        int ans=0;
        for(int i=1;i<=N;i++)
        {
            scanf("%s",s);
            place[i]=0;
            for(int j=0;j<M;j++)
            {
                place[i]<<=1;
                if(s[j]=='H')    //山地就二进制记为1
                    place[i]++; 
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=N;i++)
        {
            if(i==1)   //初始化第一行
            {
                for(int j=0;j<top&&state[j]<(1<<M);j++)
                {
                    if((state[j]&place[i])==0)   //可行状态与地形匹配
                        dp[1][j][0]=soldier[j];
                    ans=max(ans,dp[1][j][0]);
                }
            }
            else if(i==2)   //初始化第二行
            {
                for(int j=0;j<top&&state[j]<(1<<M);j++)
                {
                    if( (state[j]&place[i]) == 0 )  
                    {
                        for(int k=0;k<top&&state[k]<(1<<M);k++)
                        {
                            if( ( (state[k]&place[i-1]) ==0 ) && ( (state[k]&state[j]) ==0))  
                                //可行状态与地形匹配以及第i行可行状态与第i-1行可行状态匹配,下面也一样
                                dp[2][j][k]=dp[1][k][0]+soldier[j];  //这里是第二行,直接加,不用max函数
                            ans=max(ans,dp[2][j][k]);
                        }
                    }
                }
            }
            else
            {
                for(int j=0;j<top&&state[j]<(1<<M);j++)
                {
                    if( (state[j]&place[i]) ==0)
                    {
                        for(int k=0;k<top&&state[k]<(1<<M);k++)
                        {
                            if(( (state[k]&place[i-1]) ==0)&&( (state[k]&state[j]) ==0))
                            {
                                for(int l=0;l<top&&state[l]<(1<<M);l++)
                                {
                                    if(( (state[l]&place[i-2] )==0)&&( (state[l]&state[j]) ==0)&&( (state[l]&state[k]) ==0))
                                    {
                                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+soldier[j]);
                                    }
                                }
                            }
                            ans=max(ans,dp[i][j][k]);
                        }

                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

POJ 1185 炮兵阵地 经典状态压缩DP

先说下我个人的理解啊! 因为炮的攻击范围是上下左右两个格子  所以dp数组里面要保证存有第i行的状态和第i-1行的状态,一个三维数组搞定,同样判断的时候也要判断两行!其他的跟poj3254没什么区别!...

poj 1185 炮兵阵地 状态压缩dp

这是我第一次写状态压缩dp,刚开始毫无思路,然后网上搜了一下,经过一整天最终才看懂思路,AC。 首先,第i行与i-1行与第i-2有关(状态),于是假设dp【i】【j】=dp【i-1】【k】+状态j中炮...

POJ 1185 炮兵阵地(状态压缩dp)

1. 为何状态压缩:     棋盘规模为n*m,且m≤10,如果用一个int表示一行上棋子的状态,足以表示m≤10所要求的范围。故想到用int s[num]。至于开多大的数组,可以自己用DFS搜索试...

Poj 1185 炮兵阵地(状态压缩dp 入门题)

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17272   Accepted...

POJ1185——炮兵阵地(状态压缩dp)

炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 25195 Accept...

POJ 1185 炮兵阵地 (状态压缩DP)

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19226   Accepted...

poj 1185 炮兵阵地 【状态压缩dp】

原题链接 poj 1185 炮兵阵地        由于每行只有十个可以考虑用状态压缩,又由于每行两炮之间不能小于2,故可以先计算出,最多不会超过60种 状态,可以先存下这些状态(f[]),然后存...

poj 1185 炮兵阵地 //状态压缩DP

注意只有一行等这些特殊情况 这种状态压缩DP还是比较简单的,这个题是前2行推出下一行的状态 #include #include #include using namespac...
  • hqd_acm
  • hqd_acm
  • 2011年08月15日 21:24
  • 450

状态压缩DP poj1185 炮兵阵地

#include #include using namespace std; int map[105];//用来存地形 // map[i]的二进制表示每一行的H分布状态。 int cnt ...

poj 1185 炮兵阵地(状态压缩DP)

当你想要让代码A掉的时候,它一直不知名的wa,那绝对是一件非常痛苦的事儿;但是当你想要代码出点儿bug的时候,它测试数据全部通过,提交之后AC,其实也蛮蛋疼的。 因为刚学状压,所以我顺着思路把这个代码...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ1185 炮兵阵地 (状态压缩DP)
举报原因:
原因补充:

(最多只允许输入30个字)