zoukankan      html  css  js  c++  java
  • NOI2001 炮兵阵地详解

    【题目描述】
     
    司令部的将军们打算在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

    【题目解析】

        对于一个位置,如果它部署了一支部队,那么会对它的前后左右的2格位置产生影响,如果以行作为状态,则不能单单由上一状态转移,那样的话不能保证在它的2格处不发生矛盾,而在这个题目中,以行做状态又很明显,所以在状态的转移时必须是上一行的状态和上上行的状态一起转移,如果用f[i,j,k]来表示在第i行时,取第j个状态(注意是第j个状态),i-1行取的是第k个状态,那么不难得出状态转移方程:

         f[i,j,k]=max{f[i,j,k],f[i-1,k,l]+ff[i,j]}

        解释一下这个方程i,j,k的含义如上述,l表示在第i-2行取第l个状态,ff[i,j]表示在第i行取第j个状态时在该行放置的多少支部队,由于第二行仅与第一行有关,所以要对第二行进行一下特殊处理,对于第二行,我们有

         f[2,j,k]=max{ff[2,j]+ff[1,k]};

         这样一来,对动态规划的模型基本处理就完成了,同时我们发现,在m=10时,每一行的状态有2^10种,显然时间和空间都不能承受,必须做出优化,仔细阅读题目,发现如果一个点部署了部队,则其前后两格范围内均不能再部署部队,而且在一个格子为H时,它根本不能部署部队,因此,在许多的状态中,有许多状态是自相矛盾的,根本不需要考虑,可以用某种预处理,把状态提取出来,仅仅储存有用的状态,在这里我的方法是用深度优先搜索预处理一下,try(x:longint)为处理某一行的第x个位置,如果这个位置部署部队,那么x+1,x+2这两个位置都不能放,直接try(x+3)即可,而如果这个地方是山地,就不能放,则try(x+1),即使是平原,也可以不去部署部队,因此还原后也要try(x+1),预处理结束。

         对于状态的储存,为了简洁,用一个二进制数来表示,如当m=4时有一种状态为放,不放,不放,放,就用1代表放,0代表不放,这个二进制数为1001,转化为十进制数为9.这样状态的储存问题就迎刃而解了。

         接下来,判断状态的矛盾问题,这用到了位运算的知识,1001and0011=0001 这已经很明了了,判断两行间的状态是否矛盾,只需要用(状态1)and(状态2),如果结果是0,说明两个状态不矛盾。

    View Code
     1 program connon(input,output);
    2 var g:array[1..100,1..100] of longint;
    3 ff:array[1..100,1..100] of longint;
    4 f:array[1..100,1..100,1..100] of longint;
    5 a:array[1..100,1..10] of char;
    6 d:array[1..100] of longint;
    7 i,j,k,l,maxn,m,n,tot,sum,ans:longint;
    8 procedure init;
    9 begin
    10 readln(n,m);
    11 for i:=1 to n do
    12 begin
    13 for j:=1 to m do
    14 ead(a[i,j]);
    15 readln;
    16 end;
    17 fillchar(f,sizeof(f),0);
    18 end;
    19 function max(x,y:longint):longint;
    20 begin
    21 if x>y then
    22 exit(x)
    23 else
    24 exit(y);
    25 end;
    26 procedure dfs(x:longint);
    27 begin
    28 if x>m then
    29 begin
    30 inc(tot);
    31 g[i,tot]:=sum;
    32 ff[i,tot]:=ans;
    33 d[i]:=tot;
    34 exit;
    35 end;
    36 if a[i,x]='P' then
    37 begin
    38 sum:=sum+1<<(x-1);
    39 inc(ans);
    40 dfs(x+3);
    41 sum:=sum-1<<(x-1);
    42 dec(ans);
    43 end;
    44 dfs(x+1);
    45 end;
    46 procedure make;
    47 begin
    48 for i:=1 to d[2] do
    49 for j:=1 to d[1] do
    50 if (g[1,j] and g[2,i]=0) then
    51 f[2,i,j]:=ff[2,i]+ff[1,j];
    52 end;
    53 procedure dp;
    54 begin
    55 for i:=3 to n do
    56 for j:=1 to d[i] do
    57 for k:=1 to d[i-1] do
    58 for l:=1 to d[i-2] do
    59 if (g[i,j] and g[i-1,k]=0) then
    60 if (g[i,j] and g[i-2,l]=0) then
    61 if (g[i-1,k] and g[i-2,l]=0) then
    62 f[i,j,k]:=max(f[i,j,k],f[i-1,k,l]+ff[i,j]);
    63 end;
    64 procedure choose;
    65 var i,j,k:longint;
    66 begin
    67 maxn:=-(maxlongint>>1);
    68 for i:=1 to d[n] do
    69 for j:=1 to d[n-1] do
    70 if f[n,i,j]>maxn then
    71 maxn:=f[n,i,j];
    72 end;
    73 procedure print;
    74 begin
    75 writeln(maxn);
    76 end;
    77 begin
    78 assign(input,'connon.in');reset(input);
    79 assign(output,'connon.out');rewrite(output);
    80 init;
    81 for i:=1 to n do
    82 begin
    83 tot:=0;
    84 sum:=0;
    85 ans:=0;
    86 dfs(1);
    87 end;
    88 make;
    89 dp;
    90 choose;
    91 print;
    92 close(input);
    93 close(output);
    94 end.
  • 相关阅读:
    WPF中C#代码触发鼠标点击事件
    PHP代码实现强制换行
    C#中判断系统的架构(32位,还是64位)
    WPF的System.Windows.Threading.DispatcherTimer的使用(每隔一定的时间重复做某事)
    LINQ to Objects系列(2)两种查询语法介绍
    LINQ to Objects系列(1)相关技术准备
    常用技术社区和网站总结
    .net项目技术选型总结
    java与.net比较学习系列(7) 属性
    java与.net比较学习系列(6) 数组
  • 原文地址:https://www.cnblogs.com/neverforget/p/connon.html
Copyright © 2011-2022 走看看