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 }
  • 相关阅读:
    cf B. Sereja and Suffixes
    cf E. Dima and Magic Guitar
    cf D. Dima and Trap Graph
    cf C. Dima and Salad
    最短路径问题(floyd)
    Drainage Ditches(网络流(EK算法))
    图结构练习—BFSDFS—判断可达性(BFS)
    Sorting It All Out(拓扑排序)
    Power Network(最大流(EK算法))
    Labeling Balls(拓扑)
  • 原文地址:https://www.cnblogs.com/littlepear/p/5759287.html
Copyright © 2011-2022 走看看