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没什么区别!...
  • l133236116
  • l133236116
  • 2015年01月21日 14:51
  • 299

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

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23925   Accepted...
  • zwj1452267376
  • zwj1452267376
  • 2016年05月12日 21:29
  • 497

炮兵阵地(经典状压dp)(poj 1185) + 状压dp小技巧详解

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 22809   Accepted: 8829 ...
  • Yyyy_H
  • Yyyy_H
  • 2016年01月27日 20:58
  • 642

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

炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14787 Accepted: 5523 Descripti...
  • jianing1996
  • jianing1996
  • 2013年05月16日 16:59
  • 445

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

炮兵阵地Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 24698 Accepted: 9531Description司令部的将军们...
  • utimes
  • utimes
  • 2016年08月12日 21:18
  • 430

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

第一次接触状态压缩的动态规划,参考了别人的博客。开始写的时候一直找不到哪里错了,总觉得自己跟别人除了变量名不一样其他的都一样。后来把map数组全部输出来以后发现原来读map数组的时候就读错了,开始用的...
  • u010734277
  • u010734277
  • 2014年01月24日 17:05
  • 522

poj1185 炮兵阵地(状态压缩dp)

poj1185分析自己先写了一遍,结果没有多开一维,好菜啊,对动规的理解还不是很深入,而且自己之前写的代码也很繁杂,做的时候还是多思考吧。先预处理所有情况,由dp值是不是为-1判断前一个阶段可行不可行...
  • pibaixinghei
  • pibaixinghei
  • 2016年02月07日 21:21
  • 156

poj1185 炮兵阵地 状态压缩dp

题意很好理解 用dp[i][j][k]表示第i行状态为j并且前一行状态为k
  • smz436487
  • smz436487
  • 2014年06月03日 18:53
  • 237

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

炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 25195 Accept...
  • say_c_box
  • say_c_box
  • 2016年08月02日 17:11
  • 231

***POJ1185 炮兵阵地 ACM解题报告(状压dp入门题)

这题是个入门的状压dp(虽然对我来说好难啊,坑了一下午终于过了。。。)难得一个中文题,还这么难 注意点挺多的,首先是要开数组记录所有情况,然后记录每种情况的炮兵数,很多处理类似于前一题3254,可以...
  • Miracle_ma
  • Miracle_ma
  • 2015年02月10日 17:18
  • 603
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ1185 炮兵阵地 (状态压缩DP)
举报原因:
原因补充:

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