• pku 1185


    http://poj.org/problem?id=1185

    Description

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

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

    分析:这题和HDU 3254属于同一类题目,都是二进制状态压缩DP。不同的是,这题要难一些,同样的,刚刚开始我们先预处理每一行的可行状态,HDU3254只和前面一行构成矛盾关系,这一题的难点就是在于它的每一行和前面两行都构成了矛盾关系。此时二维数组便不够用了,应该使用三维数组dp[i][j][k]表示第i行取第j中状态并且第i-1行取第k中状态的最大部队摆放数目。

    由于每一行都和前两行有关系,那么我们就要特殊处理第一行和第二行

    对于第一行:dp[1][i][0]=i状态摆放的炮兵数目

    对于第二行:dp[2][i][k]先判断state[2][i]和state[1][k]是否矛盾,不矛盾的话dp[2][i][k]=max(dp[2][i][k],dp[1][k][0]+i状态的炮兵数目)

    对于其他:dp[i][j][k],先判断state[i][j]和state[i-1][k]是否矛盾,不矛盾的话再判断state[i][j]和state[i-2][p]是否矛盾,如果都不矛盾的话,则

    dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+i状态的炮兵数目)   //由于dp[i-1][k][p]一定是从上面得到的合法数据,且一定会大于等于i-2行的最大值,所以不需要再用i和i-2进行比较了

    最后,我们输出最后一行的最大dp值即可

    View Code
    #include<iostream>
    #include
    <string>
    #include
    <vector>
    using namespace std;
    #define maxn 70

    int dp[101][maxn+1][maxn+1];
    int n,m;
    vector
    <int>state[101];

    int lowbit(int x) //返回第一个不为0的二进制
    {
    return x&(-x);
    }

    int max(int a,int b)
    {
    return a>b?a:b;
    }

    void getstate(int i,int temp) //计算每行的合法状态
    {
    int j;
    for(j=0;j<(1<<m);j++)
    {
    if((j<<1)&j | (j>>1)&j | (j<<2)&j | (j>>2)&j)
    continue;
    if(j&temp)
    continue;
    state[i].push_back(j);
    }
    }

    int num(int temp) //计算某一个状态有多少个1,即排列了多少炮兵
    {
    int ans=0;
    while(temp)
    {
    temp
    -=lowbit(temp);
    ans
    ++;
    }
    return ans;
    }

    void solve()
    {
    int i,j,k,p;
    memset(dp,
    0,sizeof(dp));
    for(i=1;i<=n;i++)
    {
    for(j=0;j<state[i].size();j++)
    {
    int nn=num(state[i][j]);
    if(i==1) //特殊处理第一行
    {
    dp[i][j][
    0]=nn;
    }
    else if(i==2) //特殊处理第二行
    {
    for(k=0;k<state[1].size();k++)
    {
    if(state[i][j]&state[1][k])
    continue;
    dp[i][j][k]
    =max(dp[i][j][k],dp[i-1][k][0]+nn);
    }
    }
    else
    {
    for(k=0;k<state[i-1].size();k++)
    {
    if(state[i][j] & state[i-1][k])
    continue;
    for(p=0;p<state[i-2].size();p++)
    {
    if(state[i][j] & state[i-2][p])
    continue;
    dp[i][j][k]
    =max(dp[i][j][k],dp[i-1][k][p]+nn);
    }
    }
    }
    }
    }
    int ans=0;
    if(n==1)
    {
    for(i=0;i<state[n].size();i++)
    {
    ans
    =max(ans,dp[n][i][0]);
    }
    }
    else
    {
    for(i=0;i<state[n].size();i++)
    {
    for(j=0;j<state[n-1].size();j++)
    {
    ans
    =max(ans,dp[n][i][j]);
    }
    }
    }
    printf(
    "%d\n",ans);
    }

    int main()
    {
    char a[15];
    int i,j,temp;
    freopen(
    "D:\\in.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    scanf(
    "%*c");
    for(i=1;i<=n;i++)
    {
    state[i].clear();
    temp
    =0;
    scanf(
    "%s",a);
    for(j=0;j<m;j++)
    {
    if(a[j]=='P')
    temp
    =temp*2+0;
    else
    temp
    =temp*2+1;
    }
    getstate(i,temp);
    }
    solve();
    }
    return 0;
    }
  • 相关阅读:
    WMware下的Linux系统安装VMtools
    VMware虚拟机安装Ubuntu图文攻略
    Python高级编程(三)
    Python高级编程(二)
    Python高级编程(一)
    纯div+css样式弹出泡泡消息框
    EF应用CodeFirst模式,数据迁移的基本用法要点摘记
    sql左连接的误区
    ExtJs,从开始接触到如今,我都觉得你好垃圾阿。。。。
    EntityFramework经典的left join语法
  • 原文地址:https://www.cnblogs.com/ka200812/p/2135819.html
Copyright © 2020-2023  润新知