zoukankan      html  css  js  c++  java
  • poj -1185 炮兵阵地 (经典状压dp)

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

    参考博客:http://poj.org/problem?id=1185

    大神博客已经讲的很清楚了,注意存状态的时候是从1开始的,所以初始化的时候也是dp[1][1][state],从0开始的话,状态就是dp[1][0][state]了.

    dp[i][j][k]表示第i行状态为k第i-1行状态为j时的方案数.

    dp[i][j][k]=max(dp[i][j][k],dp[i-1][t][j]+num[k]); (num[k]为k状态中1的个数) 

    边界条件:dp[1][1][i]=num[i],状态i可以满足第一行的条件。

    还有就是为什么每一行最多只有60种状态,poj题目讨论里面有人给出了枚举的代码。

     1 #include <iostream>
     2 using namespace std;
     3 bool isok( int c ) {
     4     return !(c&(c<<1)||c&(c<<2));//同一行中不能有相邻的1距离小于3
     5 }
     6 int main() {
     7     int count=0;
     8     for( int i=0; i<1024; i++ )
     9         count += isok(i);
    10     cout<<count<<endl;
    11     return 0;
    12 }
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <vector>
      5 #include <cstring>
      6 #include <string>
      7 #include <algorithm>
      8 #include <string>
      9 #include <set>
     10 #include <functional>
     11 #include <numeric>
     12 #include <sstream>
     13 #include <stack>
     14 //#include <map>
     15 #include <queue>
     16 #include <deque>
     17 //#pragma comment(linker, "/STACK:102400000,102400000")
     18 #define CL(arr, val)    memset(arr, val, sizeof(arr))
     19 
     20 #define ll long long
     21 #define INF 0x7f7f7f7f
     22 #define lc l,m,rt<<1
     23 #define rc m + 1,r,rt<<1|1
     24 #define pi acos(-1.0)
     25 
     26 #define L(x)    (x) << 1
     27 #define R(x)    (x) << 1 | 1
     28 #define MID(l, r)   (l + r) >> 1
     29 #define Min(x, y)   (x) < (y) ? (x) : (y)
     30 #define Max(x, y)   (x) < (y) ? (y) : (x)
     31 #define E(x)        (1 << (x))
     32 #define iabs(x)     (x) < 0 ? -(x) : (x)
     33 #define OUT(x)  printf("%I64d
    ", x)
     34 #define lowbit(x)   (x)&(-x)
     35 #define Read()  freopen("a.txt", "r", stdin)
     36 #define Write() freopen("b.txt", "w", stdout);
     37 #define maxn 110
     38 #define maxv 5010
     39 #define mod 1000000000
     40 using namespace std;
     41 int n,m;
     42 char map[110][20],num[110],top;
     43 int stk[70],cur[110];
     44 int dp[110][70][70];
     45 
     46 inline bool ok(int x) //判断该状态是否合法,即同一行不存在相邻1之间的距离小于3的
     47 {
     48     if(x&(x<<1)||x&(x<<2)) return 0;
     49     return 1;
     50 }
     51 inline void jnite() //找到所有可能合法的状态
     52 {
     53     top=0;
     54     int total=1<<m;
     55     for(int i=0;i<total;i++)
     56         if(ok(i)) stk[++top]=i;
     57 }
     58 
     59 inline bool fit(int x,int k) //判断状态x是否与第k行匹配
     60 {
     61     if(cur[k]&x) return 0;
     62     return 1;
     63 }
     64 inline int jcount(int x) //计算一个整型数x的二进制中1的个数(用于初始化)
     65 {
     66     int cnt=0;
     67     while(x)
     68     {
     69         cnt++;
     70         x&=(x-1); //很精炼,每次都会与掉一个1 
     71     }
     72     return cnt;
     73 }
     74 int main()
     75 {
     76     //Read();
     77     while(~scanf("%d%d",&n,&m))
     78     {
     79         if(n==0&&m==0) break;
     80         jnite();
     81         for(int i=1;i<=n;i++) scanf("%s",map[i]+1);
     82         for(int i=1;i<=n;i++)
     83         {
     84             cur[i]=0;
     85             for(int j=1;j<=m;j++)
     86             {
     87                 if(map[i][j]=='H') cur[i]+=(1<<(j-1));
     88             }
     89             //printf("%d
    ",cur[i]);
     90         }
     91         memset(dp,0,sizeof(dp));
     92         for(int i=1;i<=top;i++) //初始化第一行
     93         {
     94             num[i]=jcount(stk[i]);
     95             //printf("%d
    ",num[i]);
     96             if(fit(stk[i],1)) dp[1][1][i]=num[i];
     97         }
     98         for(int i=2;i<=n;i++) {
     99             for(int t=1;t<=top;t++) {
    100                 if(!fit(stk[t],i)) continue;//第i行是否冲突
    101                 for(int j=1;j<=top;j++) { 
    102                     if(stk[t]&stk[j]) continue;//第i行和第i-2行是否冲突
    103                     for(int k=1;k<=top;k++) {
    104                         if(stk[t]&stk[k]) continue;//第i行和第i-1行是否冲突
    105                         dp[i][k][t]=max(dp[i][k][t],dp[i-1][j][k]+num[t]);
    106                       //  printf("%d
    ",dp[i][k][t]);
    107                     }
    108                 }
    109             }
    110         }
    111         int ans=0; //得到最大值
    112         for(int i=1;i<=top;i++)
    113             for(int j=1;j<=top;j++)
    114             ans=max(ans,dp[n][i][j]);
    115         printf("%d
    ",ans);
    116     }
    117     return 0;
    118 }
  • 相关阅读:
    相机用的 SD Card 锁Lock 烂掉了,无法正常写入
    Cannon 60D 电池卡在电池槽了,拔不出来怎么办?
    免费好用的 Apple 工具(Windows 适用)
    𠝹 (界刂) 呢個字點打?
    学校或公司转ISP -boardband (上网公司)注意事项记录
    iis站点添加.asmx的映射
    跨页面传参
    setTimeout和setInterval
    鼠标获取屏幕上的固定点位置坐标
    把完整字符串分割为字符串数组
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4717523.html
Copyright © 2011-2022 走看看