zoukankan      html  css  js  c++  java
  • POJ 1185炮兵阵地 (状压DP)

    题目链接 POJ 1185

    今天艾教留了一大堆线段树,表示做不动了,就补补前面的题。QAQ

    这个题,我第一次写还是像前面HDU 2167那样写,发现这次影响第 i 行的还用i-2行那样,那以前的方法就行不通了。

    找出所有可行的状态,因为每一行最大只有10列,所以一行里最多有4个,那它可行的状态不多(网上大多数说法最多是60个)。用dp[x][i][j]来转移,x表示第x行,i表示第x行的状态,j表示第x-1行的状态。先初始化前两行。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 using namespace std;
     5 const int maxn = 105;
     6 #define legal(a,b) (a&b)
     7 int base[maxn];
     8 int state[maxn];
     9 int solders[maxn];
    10 int dp[maxn][maxn][maxn];
    11 char s[maxn][20];
    12 int num = 0;
    13 int main()
    14 {
    15     int n,m;
    16     scanf("%d %d",&n,&m);
    17     for(int i=0;i<n;i++)
    18     {
    19         scanf("%s",s[i]);
    20         for(int j=0;j<m;j++)
    21         {
    22             if(s[i][j]=='H') base[i]+=(1<<j); //记录山地
    23         }
    24     }
    25     int d = 0;
    26     for(int i=0;i<(1<<m);i++) //删除一行中相互攻击的点
    27     {
    28         if(legal(i,i<<1)||legal(i,i<<2)) continue;
    29         int k = i;
    30         while(k) //记录里面有多少个炮台
    31         {
    32             solders[num]+=(1&k);
    33             k=k>>1;
    34         }
    35         state[num++] = i;
    36     }
    37     for(int i=0;i<num;i++) //初始化第0行
    38     {
    39         if(legal(state[i],base[0])) continue;
    40         dp[0][i][0] = solders[i];
    41     }
    42     for(int i=0;i<num;i++)    //初始化第1行,此为第二行
    43     {
    44         if(legal(state[i],base[1])) continue;
    45         for(int j=0;j<num;j++)          //枚举第一行
    46         {
    47             if(legal(state[j],base[0])) continue;
    48             if(legal(state[i],state[j])) continue;
    49             dp[1][i][j] = max(dp[1][i][j],dp[0][j][0]+solders[i]);
    50         }
    51     }
    52 
    53     for(int r=2;r<n;r++)   //开始从第二行枚举
    54     {
    55         for(int i=0;i<num;i++) //枚举r行
    56         {
    57             if(legal(state[i],base[r])) continue;
    58             for(int j=0;j<num;j++) //枚举r-1行
    59             {
    60                 if(legal(state[j],base[r-1])) continue;
    61                 if(legal(state[j],state[i])) continue;
    62                 for(int k=0;k<num;k++) //枚举第r-2行
    63                 {
    64                     if(legal(state[k],base[r-2])) continue;
    65                     if(legal(state[k],state[i])) continue;
    66                     if(legal(state[k],state[j])) continue;
    67                     dp[r][i][j] = max(dp[r][i][j],dp[r-1][j][k]+solders[i]);
    68                 }
    69             }
    70         }
    71     }
    72     int maxx = 0;
    73     for(int i=0;i<num;i++)
    74     {
    75         for(int j=0;j<num;j++)
    76             maxx = max(maxx,dp[n-1][i][j]);
    77     }
    78     printf("%d
    ",maxx);
    79     return 0;
    80 }
  • 相关阅读:
    AOJ 718.计算GPA
    AOJ 11.Rails
    AOJ 592.神奇的叶子
    AOJ 10.目标柏林
    洛谷P1030求先序排列
    vijos1514天才的记忆
    洛谷2016战略游戏
    LOJ10155数字转换
    洛谷2014选课
    洛谷2015二叉苹果树
  • 原文地址:https://www.cnblogs.com/littlepear/p/5759287.html
Copyright © 2011-2022 走看看