• poj1185炮兵阵地--状态dp


    炮兵阵地
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 17437   Accepted: 6669

    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

    Source

     
    分析:
    状态压缩即可,但是要注意不要判断错符合条件的式子:
    check_raw:
    num&(num<<1)==0 && num&(num<<2)==0
    check_map:
    num&map_num == num
    check_two_lie:
    a&b==0
     
    代码:
      1 #include <iostream>
      2 #include <string.h>
      3 #include <stdio.h>
      4 #include <vector>
      5 using namespace std;
      6 
      7 const int maxn=10;
      8 int dp[102][1<<maxn][1<<maxn];
      9 int map_num[102];
     10 int sum_one[1<<maxn];
     11 
     12 vector<int>v[1<<maxn][1<<maxn];
     13 vector<int>::iterator it;
     14 
     15 void get_sum_one(int m)
     16 {
     17     int len=(1<<m);
     18     for(int i=0;i<len;i++)
     19     {
     20         int num=i;
     21         int sum=0;
     22         for(int j=1;j<=num;)
     23         {
     24             if(num&j)
     25                 sum++;
     26             j<<=1;
     27         }
     28         sum_one[i]=sum;
     29     }
     30 }
     31 
     32 bool check_raw(int num)
     33 {
     34     if((num&(num<<1)) || (num&(num<<2)))
     35         return false;
     36 
     37     return true;
     38 }
     39 
     40 bool check_map(int num,int mp_num)
     41 {
     42     if((num&mp_num)==num)
     43         return true;
     44 
     45     return false;
     46 }
     47 
     48 bool check_two_lie(int a,int b)
     49 {
     50     if(a&b)
     51         return false;
     52 
     53     return true;
     54 }
     55 
     56 void init(int m)
     57 {
     58     int len=(1<<m);
     59     for(int i=0;i<len;i++)
     60     {
     61         for(int j=0;j<len;j++)
     62         {
     63             v[i][j].clear();
     64         }
     65     }
     66     for(int i=0;i<len;i++)
     67     {
     68         if(!check_raw(i))
     69             continue;
     70         for(int j=0;j<len;j++)
     71         {
     72             if(!check_raw(j))
     73                 continue;
     74             for(int k=0;k<len;k++)
     75             {
     76                 if(!check_raw(k))
     77                     continue;
     78                 if(check_two_lie(i,j) && check_two_lie(i,k) && check_two_lie(j,k))
     79                     v[i][j].push_back(k);
     80             }
     81         }
     82     }
     83 }
     84 
     85 
     86 int main()
     87 {
     88     int n,m;
     89     //freopen("ac.txt","r",stdin);
     90     while(scanf("%d %d",&n,&m)!=EOF)
     91     {
     92 
     93         //check1(m);
     94         get_sum_one(m);
     95         init(m);
     96         char str;
     97         int num;
     98         for(int i=0;i<n;i++)
     99         {
    100             int sum=0;
    101             int k=m-1;
    102             for(int j=0;j<m;j++)
    103             {
    104                 scanf("
    %c",&str);
    105                 num=(str=='P'?1:0);
    106                 sum+=num*(1<<k);
    107                 k--;
    108             }
    109             map_num[i]=sum;
    110         }
    111        // check2(n);
    112         int len=1<<m;
    113         for(int j=0;j<len;j++)
    114         {
    115             if(check_raw(j) && check_map(j,map_num[0]))
    116             {
    117                 dp[0][j][0]=sum_one[j];
    118             }
    119         }
    120         //check3(m);
    121         for(int j=0;j<len;j++)
    122         {
    123             if(!check_raw(j) || !check_map(j,map_num[1]))
    124                 continue;
    125             for(int k=0;k<len;k++)
    126             {
    127                 if(!check_raw(k) || !check_map(k,map_num[0]))
    128                 continue;
    129                 if(check_two_lie(j,k))
    130                 {
    131                     if(dp[1][j][k]<dp[0][k][0]+sum_one[j])
    132                     dp[1][j][k]=dp[0][k][0]+sum_one[j];
    133                 }
    134             }
    135         }
    136        // check4(m);
    137         for(int i=2;i<n;i++)
    138         {
    139             for(int j=0;j<len;j++)
    140             {
    141                 if(!check_map(j,map_num[i-1]))
    142                     continue;
    143                 for(int k=0;k<len;k++)
    144                 {
    145                     if(!check_map(k,map_num[i-2]))
    146                         continue;
    147                     if(v[j][k].size()){
    148                         for(int l=0;l<v[j][k].size();l++)
    149                         {
    150                             int xx=v[j][k][l];
    151                             if(check_map(xx,map_num[i]))
    152                                 if(dp[i][xx][j]<dp[i-1][j][k]+sum_one[xx])
    153                             dp[i][xx][j]=dp[i-1][j][k]+sum_one[xx];
    154                         }
    155                     }
    156                 }
    157             }
    158         }
    159         int ans=0;
    160         for(int j=0;j<len;j++)
    161         {
    162             for(int k=0;k<len;k++)
    163             {
    164                 if(ans<dp[n-1][j][k])
    165                     ans=dp[n-1][j][k];
    166             }
    167         }
    168         printf("%d
    ",ans);
    169     }
    170     return 0;
    171 }
    View Code
     
  • 相关阅读:
    Socket
    利用Python自动生成暴力破解的字典
    【转】六年测试工作的思考1
    【转】手机测试入行三年的感想
    【转】移动测试人员的未来:测试开发技术的融合
    【转】一个互联网项目即将结束的软件测试经验总结
    【转】电子商务网站测试经验总结
    【转】六年软件测试感悟-从博彦到VMware
    使用PL/SQL删除百万条记录的大表
    【转】百万级数据查询优化
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/3652663.html
Copyright © 2020-2023  润新知