zoukankan      html  css  js  c++  java
  • 插头DP

    一般是求网格图路径个数/最值的。

    维护轮廓线连通性。按照格子转移。

    参考资料题单

    注意跨行时的转移。

    例题:bzoj1814  注意!结尾不一定是(n, m),此时要保证没有插头才能加入答案。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <cmath>
      5 
      6 typedef long long LL;
      7 const int N = 14, M = 1600000;
      8 
      9 LL f[2][M];
     10 int n, m, G[N][N], now[N], state[M], id[M], top;
     11 char str[N];
     12 
     13 inline int zip(int *a) {
     14     int ans = 0;
     15     for(int i = m; i >= 0; i--) {
     16         ans = ans * 3 + a[i];
     17     }
     18     return id[ans];
     19 }
     20 
     21 inline void DFS(int k, int cnt, int sta) {
     22     if(k > m) {
     23         if(cnt == 0) {
     24             state[++top] = sta;
     25             id[sta] = top;
     26             //printf("state ++top = %d 
    ", state[top]);
     27         }
     28         return;
     29     }
     30     DFS(k + 1, cnt, sta * 3);
     31     if(cnt) {
     32         DFS(k + 1, cnt - 1, sta * 3 + 1);
     33     }
     34     DFS(k + 1, cnt + 1, sta * 3 + 2);
     35     return;
     36 }
     37 
     38 inline void prework() {
     39     DFS(0, 0, 0);
     40     return;
     41 }
     42 
     43 inline void unzip(int x, int *a) { // m + 1
     44     x = state[x];
     45     for(int i = 0; i <= m; i++) {
     46         a[i] = x % 3;
     47         x /= 3;
     48     }
     49     return;
     50 }
     51 
     52 inline void add(LL &a, LL b) {
     53     a += b;
     54     return;
     55 }
     56 
     57 inline void out() {
     58     for(int i = 0; i <= m; i++) {
     59         printf("%d", now[i]);
     60     }
     61     return;
     62 }
     63 
     64 inline int get2(int p) {
     65     int cnt = 0;
     66     while(1) {
     67         //printf("get 2 
    ");
     68         if(now[p] == 2 && !cnt) {
     69             return p;
     70         }
     71         if(now[p] == 1) {
     72             cnt++;
     73         }
     74         else if(now[p] == 2) {
     75             cnt--;
     76         }
     77         p++;
     78     }
     79 }
     80 
     81 inline int get1(int p) {
     82     int cnt = 0;
     83     while(1) {
     84         //printf("get 1 
    ");
     85         if(now[p] == 1 && !cnt) {
     86             return p;
     87         }
     88         if(now[p] == 2) {
     89             cnt++;
     90         }
     91         else if(now[p] == 1) {
     92             cnt--;
     93         }
     94         p--;
     95     }
     96 }
     97 
     98 inline char gc() {
     99     char c = getchar();
    100     while(c != '*' && c != '.') c = getchar();
    101     return c;
    102 }
    103 
    104 int main() {
    105 
    106     //printf("%d", sizeof(f) / 1048576);
    107     //freopen("in.in", "r", stdin);
    108     //freopen("my.out", "w", stdout);
    109 
    110     scanf("%d%d", &n, &m);
    111     for(int i = 0; i < n; i++) {
    112         for(int j = 0; j < m; j++) {
    113             G[i][j] = (gc() == '*');
    114         }
    115     }
    116 
    117     int last_x, last_y;
    118     for(int i = n - 1; i >= 0; i--) {
    119         for(int j = m - 1; j >= 0; j--) {
    120             if(!G[i][j]) {
    121                 last_x = i;
    122                 last_y = j;
    123                 i = -1;
    124                 break;
    125             }
    126         }
    127     }
    128 
    129     prework();
    130 
    131     int lm = pow(3, m + 1), flag = 1;
    132     LL ans = 0;
    133     f[0][id[0]] = 1;
    134     for(int i = 0; i < n; i++) {
    135         for(int j = 0; j < m; j++) {
    136             flag ^= 1;
    137             for(int s = 1; s <= top; s++) {
    138                 f[flag ^ 1][s] = 0;
    139             }
    140             //printf("%d %d 
    ", i, j);
    141             for(int s = 1; s <= top; s++) {
    142                 if(!f[flag][s]) {
    143                     continue;
    144                 }
    145                 unzip(s, now);
    146                 // f[i][j][s] -> f[i][j + 1][?]
    147                 /// now[j] now[j + 1]
    148                 // DP
    149                 LL c = f[flag][s];
    150                 //printf(" > > s :"); out(); printf(" %d 
    ", c);
    151                 if(G[i][j]) {
    152                     if(!now[j] && !now[j + 1]) {
    153                         add(f[flag ^ 1][s], c);
    154                     }
    155                     continue;
    156                 }
    157                 if(!now[j] && !now[j + 1]) { /// 0 0
    158                     now[j] = 1;
    159                     now[j + 1] = 2;
    160                     add(f[flag ^ 1][zip(now)], c);
    161                     now[j] = now[j + 1] = 0;
    162                 }
    163                 else if(!now[j] || !now[j + 1]) { /// [0  1/2]  [1/2  0]  hold / swap
    164                     add(f[flag ^ 1][s], c);
    165                     std::swap(now[j], now[j + 1]);
    166                     add(f[flag ^ 1][zip(now)], c);
    167                     std::swap(now[j], now[j + 1]);
    168                 }
    169                 else if(now[j] == 1 && now[j + 1] == 1) { /// 1 1   the first 2 -> 1
    170                     int p = get2(j + 2);
    171                     now[p] = 1; now[j] = now[j + 1] = 0;
    172                     add(f[flag ^ 1][zip(now)], c);
    173                     now[p] = 2; now[j] = now[j + 1] = 1;
    174                 }
    175                 else if(now[j] == 2 && now[j + 1] == 2) { /// 2 2   the first 1 -> 2
    176                     int p = get1(j - 1);
    177                     now[p] = 2; now[j] = now[j + 1] = 0;
    178                     add(f[flag ^ 1][zip(now)], c);
    179                     now[1] = 1; now[j] = now[j + 1] = 2;
    180                 }
    181                 else if(now[j] == 2 && now[j + 1] == 1) { /// 2 1  merge
    182                     now[j] = now[j + 1] = 0;
    183                     add(f[flag ^ 1][zip(now)], c);
    184                     now[j] = 2; now[j + 1] = 1;
    185                 }
    186                 else if(i == last_x && j == last_y) { /// 1 2  END
    187                     bool t = 0;
    188                     for(int q = 0; q < j; q++) {
    189                         if(now[q]) {
    190                             t = 1;
    191                             break;
    192                         }
    193                     }
    194                     for(int q = j + 2; q <= m; q++) {
    195                         if(now[q]) {
    196                             t = 1;
    197                             break;
    198                         }
    199                     }
    200                     if(!t) add(ans, c);
    201                 }
    202             }
    203         }
    204         if(i < n - 1) {
    205             // change row
    206             for(int s = top; s >= 1; s--) {
    207                 if(state[s] % 3) {
    208                     f[flag ^ 1][s] = 0;
    209                 }
    210                 else {
    211                     f[flag ^ 1][s] = f[flag ^ 1][id[state[s] / 3]];
    212                 }
    213             }
    214         }
    215     }
    216 
    217     printf("%lld
    ", ans);
    218     return 0;
    219 }
    AC代码

    例题:hdu1693  不用记录左/右插头,直接DP,随意转移。

      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 typedef long long LL;
      5 const int N = 13;
      6 
      7 int G[N][N], m, n;
      8 LL f[2][1480010];
      9 
     10 inline void add(LL &a, LL b) {
     11     a += b;
     12     return;
     13 }
     14 
     15 inline void out(int x) {
     16     printf("%d ", x);
     17     for(int i = 0; i <= m; i++) {
     18         printf("%d", (x >> i) & 1);
     19     }
     20     return;
     21 }
     22 
     23 /*
     24 2
     25 2 4
     26 1 1 1 1
     27 1 1 1 1
     28 */
     29 
     30 inline LL solve() {
     31     memset(f, 0, sizeof(f));
     32     scanf("%d%d", &n, &m);
     33     int last_x, last_y;
     34     for(int i = 0; i < n; i++) {
     35         for(int j = 0; j < m; j++) {
     36             scanf("%d", &G[i][j]);
     37             if(G[i][j]) {
     38                 last_x = i;
     39                 last_y = j;
     40             }
     41             G[i][j] ^= 1;
     42         }
     43     }
     44 
     45     int lm = 1 << (m + 1), flag = 1;
     46     LL ans = 0;
     47     f[0][0] = 1;
     48     for(int i = 0; i < n; i++) {
     49         for(int j = 0; j < m; j++) {
     50             flag ^= 1;
     51             //printf("%d %d 
    ", i, j);
     52             for(int s = 0; s < lm; s++) {
     53                 f[flag ^ 1][s] = 0;
     54             }
     55             for(int s = 0; s < lm; s++) {
     56                 //printf("f %d %d = %d 
    ", flag, s, f[flag][s]);
     57                 if(!f[flag][s]) {
     58                     continue;
     59                 }
     60                 int a = (s >> j) & 1, b = (s >> (j + 1)) & 1;
     61                 LL c = f[flag][s];
     62                 //printf(" > s : "); out(s); printf(" = %d 
    ", c);
     63                 if(G[i][j]) {
     64                     if(!a && !b) {
     65                         add(f[flag ^ 1][s], c);
     66                     }
     67                 }
     68                 else if(!a && !b) { /// 0 0
     69                     add(f[flag ^ 1][s | (1 << j) | (1 << (j + 1))], c);
     70                     //printf(" ---> %d %d 
    ", flag ^ 1, s | (1 << j) | (1 << (j + 1)));
     71                 }
     72                 else if(a && b) {
     73                     add(f[flag ^ 1][s & (~((1 << j) | (1 << (j + 1))))], c);
     74                 }
     75                 else if(a) {
     76                     add(f[flag ^ 1][s], c);
     77                     add(f[flag ^ 1][(s | (1 << (j + 1))) & (~(1 << j))], c);
     78                 }
     79                 else if(b) {
     80                     add(f[flag ^ 1][s], c);
     81                     add(f[flag ^ 1][(s | (1 << j)) & (~(1 << (j + 1)))], c);
     82                 }
     83             }
     84             if(i == last_x && j == last_y) {
     85                 return f[flag ^ 1][0];
     86             }
     87         }
     88         /// line i -> i + 1
     89         for(int s = lm - 1; s >= 0; s--) {
     90             if(s & 1) {
     91                 f[flag ^ 1][s] = 0;
     92             }
     93             else {
     94                 f[flag ^ 1][s] = f[flag ^ 1][s >> 1];
     95             }
     96         }
     97     }
     98     return -1;
     99 }
    100 
    101 int main() {
    102     int T;
    103     scanf("%d", &T);
    104     for(int i = 1; i <= T; i++) {
    105         LL ans = solve();
    106         printf("Case %d: There are %lld ways to eat the trees.
    ", i, ans);
    107         //printf("%lld 
    ", ans);
    108     }
    109     return 0;
    110 }
    AC代码

    例题:poj3133 求把网格图上2和3连通起来的最小格子数。

    求最值,一样的套路...

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <algorithm>
      5 
      6 const int N = 15, INF = 0x3f3f3f3f;
      7 
      8 int G[N][N], now[N], m, n;
      9 int f[2][60010];
     10 
     11 inline int zip(int *a) {
     12     int ans = 0;
     13     for(int i = m; i >= 0; i--) {
     14         ans = ans * 3 + a[i];
     15     }
     16     return ans;
     17 }
     18 
     19 inline void unzip(int x, int *a) {
     20     for(int i = 0; i <= m; i++) {
     21         a[i] = x % 3;
     22         x /= 3;
     23     }
     24     return;
     25 }
     26 
     27 inline void out() {
     28     for(int i = 0; i <= m; i++) {
     29         printf("%d", now[i]);
     30     }
     31     return;
     32 }
     33 
     34 inline void exmin(int &x, int y) {
     35     x > y ? x = y : 0;
     36     return;
     37 }
     38 
     39 inline void solve() {
     40     memset(f, 0x3f, sizeof(f));
     41     int last_x, last_y;
     42     for(int i = 0; i < n; i++) {
     43         for(int j = 0; j < m; j++) {
     44             scanf("%d", &G[i][j]);
     45             if(G[i][j] != 1) {
     46                 last_x = i;
     47                 last_y = j;
     48             }
     49             if(G[i][j] == 1 || G[i][j] == 3) {
     50                 G[i][j] = 4 - G[i][j];
     51             }
     52         }
     53     }
     54 
     55     int flag = 1, lm = pow(3, m + 1);
     56     f[0][0] = 0;
     57     for(int i = 0; i < n; i++) {
     58         for(int j = 0; j < m; j++) {
     59             flag ^= 1;
     60             for(int s = 0; s < lm; s++) {
     61                 f[flag ^ 1][s] = INF;
     62             }
     63             //printf("%d %d 
    ", i, j);
     64             for(int s = 0; s < lm; s++) {
     65                 if(f[flag][s] == INF) {
     66                     continue;
     67                 }
     68                 unzip(s, now);
     69                 int c = f[flag][s], &a = now[j], &b = now[j + 1];
     70 
     71                 //printf("   "); out(); printf(" = %d 
    ", c);
     72 
     73                 if(G[i][j] == 3) {
     74                     if(!a && !b) {
     75                         exmin(f[flag ^ 1][s], c);
     76                     }
     77                 }
     78                 else if(G[i][j] == 1) {
     79                     if(a == 1 && !b) {
     80                         a = 0;
     81                         exmin(f[flag ^ 1][zip(now)], c + 1);
     82                         a = 1;
     83                     }
     84                     else if(b == 1 && !a) {
     85                         b = 0;
     86                         exmin(f[flag ^ 1][zip(now)], c + 1);
     87                         b = 1;
     88                     }
     89                     else if(!a && !b) {
     90                         a = 1;
     91                         exmin(f[flag ^ 1][zip(now)], c + 1);
     92                         a = 0;
     93                         b = 1;
     94                         exmin(f[flag ^ 1][zip(now)], c + 1);
     95                         b = 0;
     96                     }
     97                 }
     98                 else if(G[i][j] == 2) {
     99                     if(a == 2 && !b) {
    100                         a = 0;
    101                         exmin(f[flag ^ 1][zip(now)], c + 1);
    102                         a = 2;
    103                     }
    104                     else if(b == 2 && !a) {
    105                         b = 0;
    106                         exmin(f[flag ^ 1][zip(now)], c + 1);
    107                         b = 2;
    108                     }
    109                     else if(!a && !b) {
    110                         a = 2;
    111                         exmin(f[flag ^ 1][zip(now)], c + 1);
    112                         a = 0;
    113                         b = 2;
    114                         exmin(f[flag ^ 1][zip(now)], c + 1);
    115                         b = 0;
    116                     }
    117                 } /// G[i][j] == 0
    118                 else if(!a && !b) { /// 0 0
    119                     exmin(f[flag ^ 1][s], c); // not choose
    120                     a = b = 1;
    121                     exmin(f[flag ^ 1][zip(now)], c + 1); // choose 1
    122                     a = b = 2;
    123                     exmin(f[flag ^ 1][zip(now)], c + 1); // choose 2
    124                     a = b = 0;
    125                 }
    126                 else if(b == 1 && a == 1) { /// 1 1 merge
    127                     a = b = 0;
    128                     exmin(f[flag ^ 1][zip(now)], c + 1);
    129                     a = b = 1;
    130                 }
    131                 else if(a == 2 && b == 2) { /// 2 2 merge
    132                     a = b = 0;
    133                     exmin(f[flag ^ 1][zip(now)], c + 1);
    134                     a = b = 2;
    135                 }
    136                 else if(a == 0 || b == 0) { /// a=0 / b=0  swap
    137                     exmin(f[flag ^ 1][s], c + 1);
    138                     std::swap(a, b);
    139                     exmin(f[flag ^ 1][zip(now)], c + 1);
    140                     std::swap(a, b);
    141                 }
    142             }
    143             if(i == last_x && j == last_y) {
    144                 if(f[flag ^ 1][0] == INF) puts("0");
    145                 else printf("%d
    ", f[flag ^ 1][0] - 2);
    146                 return;
    147             }
    148         }
    149         for(int s = lm - 1; s >= 0; s--) {
    150             if(s % 3) {
    151                 f[flag ^ 1][s] = INF;
    152             }
    153             else {
    154                 f[flag ^ 1][s] = f[flag ^ 1][s / 3];
    155             }
    156         }
    157     }
    158 
    159     return;
    160 }
    161 
    162 int main() {
    163     scanf("%d%d", &n, &m);
    164     while(n) {
    165         solve();
    166         scanf("%d%d", &n, &m);
    167     }
    168     return 0;
    169 }
    AC代码
  • 相关阅读:
    交叉编译fw_printenv
    解压 xxxx.cpio.gz.u-boot
    创建Uboot 环境变量 bin 文件
    Linux快速显示图片
    移动终端的GPU显卡介绍
    Video Mode Timings
    change systemd service
    device tree DTB DTC 相互转换
    如何写出安全的API接口(参数加密+超时处理+私钥验证+Https)- 续(附demo)
    解决h5在ios 微信中 input框键盘收起 页面底部留白
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10423472.html
Copyright © 2011-2022 走看看