• POJ 1185 炮兵阵地(状压dp)


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

    题意:

    思路:

    每一行最多只有10列,所以可以用二进制来表示每一行的状态。

    d【i】【j】【k】表示第i行状态为k时,并且上一行状态为j时的最大炮兵数。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn = 20+5;
     17 
     18 int n, m;
     19 
     20 char s[20];
     21 int st[105];
     22 int tmp[105];
     23 int num[105];
     24 int d[105][105][105];
     25 
     26 int calc(int x)
     27 {
     28     int tmp=0;
     29     while(x)
     30     {
     31         if(x&1)  tmp++;
     32         x>>=1;
     33     }
     34     return tmp;
     35 }
     36 
     37 int main()
     38 {
     39     //freopen("in.txt","r",stdin);
     40     while(~scanf("%d%d",&n, &m))
     41     {
     42         getchar();
     43         for(int i=1;i<=n;i++)
     44         {
     45             scanf("%s",&s);
     46             st[i]=0;
     47             for(int j=0;j<m;j++)
     48             {
     49                 st[i]=(st[i]<<1)|(s[j]=='P');
     50             }
     51         }
     52 
     53         int top=0;
     54         for(int i=0;i<(1<<m);i++)  //记录可行状态
     55         {
     56             if(!(i&(i<<1)) && !(i&(i<<2)))
     57             {
     58                 tmp[top]=i;
     59                 num[top]=calc(i);
     60                 top++;
     61             }
     62         }
     63 
     64         int ans=0;
     65         memset(d,-1,sizeof(d));
     66         for(int i=0;i<top;i++)  //第一行状态
     67         {
     68             if((st[1]|tmp[i])==st[1])   d[1][0][i]=num[i];
     69         }
     70 
     71         for(int i=2;i<=n;i++)
     72         {
     73             for(int j=0;j<top;j++)  //第i行状态
     74             {
     75                 if((st[i]|tmp[j])!=st[i])  continue;
     76 
     77                 for(int k=0;k<top;k++)  //第i-1行状态
     78                 {
     79                     if((st[i-1]|tmp[k])!=st[i-1])  continue;
     80                     if(tmp[j]&tmp[k])  continue;  //和第i行有冲突
     81 
     82                     for(int t=0;t<top;t++)  //第i-2行状态
     83                     {
     84                         if(i>2)
     85                         {
     86                             if((st[i-2]|tmp[t])!=st[i-2])  continue;
     87                             if(tmp[t]&tmp[k])  continue;
     88                             if(tmp[t]&tmp[j])  continue;
     89                         }
     90 
     91                         d[i][k][j]=max(d[i][k][j],d[i-1][t][k]+num[j]);
     92                     }
     93                 }
     94             }
     95         }
     96         
     97         for(int i=0;i<top;i++)
     98             for(int j=0;j<top;j++)
     99             ans=max(ans,d[n][i][j]);
    100         printf("%d
    ", ans);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    SQL SERVER中一些常见性能问题的总结
    【BZOJ2554】Color 概率神题
    【BZOJ1818】[Cqoi2010]内部白点 扫描线+树状数组
    【BZOJ1879】[Sdoi2009]Bill的挑战 状压DP
    【BZOJ2668】[cqoi2012]交换棋子 费用流
    【BZOJ4372】烁烁的游戏 动态树分治+线段树
    【BZOJ3470】Freda’s Walk 概率与期望
    【BZOJ2087】[Poi2010]Sheep 几何+DP
    【BZOJ4428】[Nwerc2015]Debugging调试 记忆化搜索+分块
    【BZOJ2137】submultiple 高斯消元求伯努利数
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7092845.html
Copyright © 2020-2023  润新知