zoukankan      html  css  js  c++  java
  • poj-1185 炮兵阵地

    炮兵阵地
    Time Limit: 2000MS Memory Limit: 65536K
    Total Submissions: 22654 Accepted: 8774
    Description

    司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用”H” 表示),也可能是平原(用”P”表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:

    如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
    现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
    Input

    第一行包含两个由空格分割开的正整数,分别表示N和M;
    接下来的N行,每一行含有连续的M个字符(‘P’或者’H’),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
    Output

    仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
    Sample Input

    5 4
    PHPP
    PPHH
    PPPP
    PHPP
    PHHP
    Sample Output

    6
    这是一个典型的动态规划问题,在我的现有知识里,我把它划分为在地图上的动态规划,我建议写这一道题目之前先写一下HOJ-2662,这个比较简单。而且这个题目是问最多能摆的数量,hoj-2662,问的是最多方案,二者的状态转移方程一个是求和,一个是求最大值。这类题目的思路都是一样的,首先要进行状态压缩,把每一行的状态进行二进制压缩。然后运用动态规划的思想,一行一行的递推,而且,这道题目,由于决定该行状态是否合理是由上面两行决定的,所以要用到三维的数组,表示i行,i-1行,能摆的最大数量。所以状态转移方程dp[i][j][s1]=max(dp[i][j][s1],get(s[j],i)+dp[i-1][s1][v];这类题目,巧妙的运用位运算:
    a&b:表示a状态和b状态,同一列是否有都是1的情况
    (a<<1)&b||(a>>1)&b: 表示a状态和b状态,是否存在曼哈顿距离为2的情况,具体见http://acm.hdu.edu.cn/diy/contest_showproblem.php?pid=1004&cid=20939
    判断左右是否相邻
    x&(x<<1)
    左右是否距离两个格子
    x&(x<<2);
    ……
    这道题目还有一个需要特别注意的地方,就是事先进行判断哪些状态是不符合的,直接筛选,这样状态数量大大减少,因为我们要套3个for循环,所以不这张做肯定会爆掉,超时

    关于位运算
    http://blog.csdn.net/Dacc123/article/details/50974579

    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    
    using namespace std;
    int dp[105][105][105];//第i行第i-1行状态,,炮兵数量
    int s[105];
    int n,m;
    char a[105][15];
    #define MAX 65
    int cnt;
    int get(int x,int row)
    {
        int res=0;
        int i=0;
        int x2;
        int t=0;
        while(x)
        {
    
    
            if(res=(x&1))
                t++;
            x>>=1;
            //判断是否为平原
            if(res&&a[row][i]=='H')
                return -1;
            i++;
        }
        return t;
    
    }
    bool ok(int x)
    {
        if(x&(x<<1)) return false;
        if(x&(x<<2)) return false;
        return true;
    }
    void init()
    {
        memset(s,0,sizeof(s));
        for(int i=0;i<(1<<m);i++)
        {
                if(ok(i))
                {
                    s[cnt++]=i;
                }
        }
    }
    
    
    int main()
    {
    char b;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
    
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                {
                    cin>>b;
    a[i][j]=b;
                }
    
            }
            cnt=0;
            init();
            memset(dp,0,sizeof(dp));
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<cnt;j++)
                {
                    if(get(s[j],i)!=-1)//如果当前状态符合条件
                    {
                        if(i==0)
                        {
                            dp[0][j][0]=max(0,get(s[j],i));
                            continue;
                        }
    
                        //第i-1行
                        for(int s1=0;s1<cnt;s1++)
                        {
                            if(i==1)
                            {
                                dp[i][j][s1]=max(dp[i][j][s1],get(s[j],i)+dp[i-1][s1][0]);
                                continue;
                            }
    
                            //第i-2行
                            for(int v=0;v<cnt;v++)
                            {
                                if((!(s[s1]&s[v]))&&(!(s[j]&s[v]))&&(!(s[j]&s[s1])))
                                {
    
                                if(get(s[s1],i-1)!=-1&&get(s[v],i-2)!=-1)
                                {
    
                                   dp[i][j][s1]=max(dp[i][j][s1],get(s[j],i)+dp[i-1][s1][v]);
                                }
                                }
                            }
    
    
                        }
    
                    }
    
    
                }
            }
    
            int max=0;
            for(int i=0;i<cnt;i++)
            {
                for(int j=0;j<cnt;j++)
                {
                    if(max<dp[n-1][i][j])
                        max=dp[n-1][i][j];
                }
            }
            printf("%d
    ",max);
        }
    }
  • 相关阅读:
    单例模式
    HashSet、LinkedHashSet、SortedSet、TreeSet
    ArrayList、LinkedList、CopyOnWriteArrayList
    HashMap、Hashtable、LinkedHashMap
    andrew ng machine learning week8 非监督学习
    andrew ng machine learning week7 支持向量机
    andrew ng machine learning week6 机器学习算法理论
    andrew ng machine learning week5 神经网络
    andrew ng machine learning week4 神经网络
    vue组件监听属性变化watch方法报[Vue warn]: Method "watch" has type "object" in the component definition. Did you reference the function correctly?
  • 原文地址:https://www.cnblogs.com/dacc123/p/8228858.html
Copyright © 2011-2022 走看看