zoukankan      html  css  js  c++  java
  • 插头DP题目泛做(为了对应WYD的课件)

    题目1:BZOJ 1814 URAL 1519 Formula 1

    题目大意:给定一个N*M的棋盘,上面有障碍格子。求一个经过所有非障碍格子形成的回路的数量。

    插头DP入门题。记录连通分量。

      1 #include <bits/stdc++.h>
      2  
      3 using namespace std;
      4  
      5 const int maxd = 15;
      6 const int hash = 30007;
      7 const int State = 1000010;
      8 typedef long long ll;
      9  
     10 ll ans = 0;
     11 int n, m;
     12 int maze[maxd][maxd];
     13 int code[maxd], ch[maxd];
     14 int end_x, end_y;
     15 char str[maxd];
     16  
     17 struct HashMap {
     18   int head[hash], next[State], size;
     19   ll state[State], f[State];
     20  
     21   void Init() {
     22     size = 0;
     23     memset(head, -1, sizeof head);
     24   }
     25  
     26   void push(ll st, ll ans) {
     27     int h = st % hash;
     28  
     29     for(int i = head[h]; i != -1; i = next[i]) {
     30       if(state[i] == st) {
     31         f[i] += ans;
     32         return;
     33       }
     34     }
     35     state[size] = st;
     36     f[size] = ans;
     37     next[size] = head[h];
     38     head[h] = size ++;
     39   }
     40 }dp[2];
     41  
     42 void decode(int *code, int s, ll st) {
     43   for(int i = s; i >= 0; -- i) {
     44     code[i] = st & 7;
     45     st >>= 3;
     46   }
     47 }
     48  
     49  
     50 ll encode(int *code, int s) {
     51   int cnt = 1;
     52   ll st = 0;
     53  
     54   memset(ch, -1, sizeof ch);
     55   ch[0] = 0;
     56   for(int i = 0; i <= s; ++ i) {
     57     if(ch[code[i]] == -1) ch[code[i]] = cnt ++;
     58     code[i] = ch[code[i]];
     59     st <<= 3;
     60     st |= code[i];
     61   }
     62   return st;
     63 }
     64  
     65 void Shit(int *code, int s) {
     66   for(int i = s; i >= 0; -- i)
     67     code[i] = code[i - 1];
     68   code[0] = 0;
     69 }
     70  
     71 void dpblank(int x, int y, int cur) {
     72   int left, up;
     73  
     74   for(int i = 0; i < dp[cur].size; ++ i) {
     75     decode(code, m, dp[cur].state[i]);
     76     left = code[y - 1];
     77     up = code[y];
     78  
     79     if(left && up) {
     80       if(left == up) {
     81         if(x == end_x && y == end_y) {
     82           code[y - 1] = code[y] = 0;
     83           if(y == m) Shit(code, m);
     84           dp[cur ^ 1].push(encode(code, m), dp[cur].f[i]);
     85         }
     86       }
     87       else {
     88         code[y - 1] = code[y] = 0;
     89         for(int j = 0; j <= m; ++ j)
     90           if(code[j] == up)
     91             code[j] = left;
     92         if(y == m) Shit(code, m);
     93         dp[cur ^ 1].push(encode(code, m), dp[cur].f[i]);
     94       }
     95     }
     96     else if((left && !up) || (!left && up)) {
     97       int t;
     98  
     99       if(left) t = left;
    100       else t = up;
    101       if(maze[x][y + 1]){
    102         code[y - 1] = 0;
    103         code[y] = t;
    104         dp[cur ^ 1].push(encode(code, m), dp[cur].f[i]);
    105       }
    106       if(maze[x + 1][y]) {
    107         code[y - 1] = t;
    108         code[y] = 0;
    109         if(y == m) Shit(code, m);
    110         dp[cur ^ 1].push(encode(code, m), dp[cur].f[i]);
    111       }
    112     }
    113     else {
    114       if(maze[x][y + 1] && maze[x + 1][y]) {
    115         code[y - 1] = code[y] = 13;
    116         dp[cur ^ 1].push(encode(code, m), dp[cur].f[i]);
    117       }
    118     }
    119   }
    120 }
    121  
    122 void dpblock(int x, int y, int cur) {
    123   for(int i = 0; i < dp[cur].size; ++ i) {
    124     decode(code, m, dp[cur].state[i]);
    125     code[y - 1] = code[y] = 0;
    126     if(y == m) Shit(code, m);
    127     dp[cur ^ 1].push(encode(code, m), dp[cur].f[i]);
    128   }
    129 }
    130  
    131 void Input() {
    132   memset(maze, 0, sizeof maze);
    133  
    134   scanf("%d%d", &n, &m);
    135   for(int i = 1; i <= n; ++ i) {
    136     scanf("%s", str + 1);
    137     for(int j = 1; j <= m; ++ j) {
    138       if(str[j] == '.') {
    139         maze[i][j] = 1;
    140         end_x = i; end_y = j;
    141       }
    142     }
    143   }
    144 }
    145  
    146 void Solve() {
    147   int cur = 0;
    148   ans = 0;
    149  
    150   dp[cur].Init();
    151   dp[cur].push(0, 1);
    152   for(int i = 1; i <= n; ++ i) {
    153     for(int j = 1; j <= m; ++ j) {
    154       dp[cur ^ 1].Init();
    155       if(maze[i][j]) dpblank(i, j, cur);
    156       else dpblock(i, j, cur);
    157       cur ^= 1;
    158     }
    159   }
    160  
    161   for(int i = 0; i < dp[cur].size; ++ i) {
    162     ans += dp[cur].f[i];
    163   }
    164  
    165 }
    166  
    167 void Output() {
    168   printf("%lld
    ", ans);
    169 }
    170  
    171 int main(){
    172   Input();
    173   Solve();
    174   Output();
    175  
    176   return 0; 
    177 }
    BZOJ 1814

    题目2:HDU 1693

    求障碍棋盘上面多回路数。

    因为求多回路,所以不一定在最后一个非障碍格子形成回路。只要当前状态相邻的两个格子有下插头和右插头,就是一个新的回路。所以对于此时的插头来说,我们可以不记插头所在的连通分量,只记录其是否存在即可。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <cmath>
      7 
      8 using namespace std;
      9 
     10 const int maxd = 15;
     11 const int Hash = 30007;
     12 const int State = 1000010;
     13 typedef long long ll;
     14 
     15 ll ans = 0;
     16 int n, m;
     17 int maze[maxd][maxd];
     18 int code[maxd];
     19 
     20 struct HashMap {
     21   int head[Hash], next[State], size;
     22   ll state[State], f[State];
     23 
     24   void Init() {
     25     size = 0;
     26     memset(head, -1, sizeof head);
     27   }
     28 
     29   void push(ll st, ll ans) {
     30     int h = st % Hash;
     31 
     32     for(int i = head[h]; i != -1; i = next[i]) {
     33       if(state[i] == st) {
     34         f[i] += ans;
     35         return;
     36       }
     37     }
     38 
     39     f[size] = ans;
     40     state[size] = st;
     41     next[size] = head[h];
     42     head[h] = size ++;
     43   }
     44 }dp[2];
     45 
     46 void opencode(int *code, int s, ll st) {
     47   for(int i = s; i >= 0; -- i) {
     48     code[i] = st & 1;
     49     st >>= 1;
     50   }
     51 }
     52 
     53 ll lockcode(int *code, int s) {
     54   ll st = 0;
     55 
     56   for(int i = 0; i <= s; ++ i) {
     57     st <<= 1;
     58     st |= code[i];
     59   }
     60 
     61   return st;  
     62 }
     63 
     64 void Shit(int *code, int s) {
     65   for(int i = s; i >= 1; -- i) {
     66     code[i] = code[i - 1];
     67   }
     68   code[0] = 0;
     69 }
     70 
     71 void dpblank(int x, int y, int cur) {
     72   int left, up;
     73 
     74   for(int i = 0; i < dp[cur].size; ++ i) {
     75     opencode(code, m, dp[cur].state[i]);
     76     left = code[y - 1];
     77     up = code[y];
     78     if(left && up) {
     79       code[y - 1] = code[y] = 0;
     80       if(y == m) Shit(code, m);
     81       dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
     82     }
     83     else if(left || up) {
     84       if(maze[x][y + 1]) {
     85         code[y - 1] = 0;
     86         code[y] = 1;
     87         dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
     88       }
     89       if(maze[x + 1][y]) {
     90         code[y - 1] = 1;
     91         code[y] = 0;
     92         if(y == m) Shit(code, m);
     93         dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
     94       }
     95     }
     96     else {
     97       if(maze[x + 1][y] && maze[x][y + 1]) {
     98         code[y - 1] = code[y] = 1;
     99         dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
    100       }
    101     }
    102   }
    103 }
    104 
    105 void dpblock(int x, int y, int cur) {
    106   for(int i = 0; i < dp[cur].size; ++ i) {
    107     opencode(code, m, dp[cur].state[i]);
    108     code[y - 1] = code[y] = 0;
    109     if(y == m) Shit(code, m);
    110     dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
    111   }
    112 }
    113 
    114 
    115 void Input() {
    116   scanf("%d%d", &n, &m);
    117   memset(maze, 0, sizeof maze);
    118   for(int i = 1; i <= n; ++ i) {
    119     for(int j = 1; j <= m; ++ j) {
    120       scanf("%d", &maze[i][j]);
    121     }
    122   }
    123 }
    124 
    125 void Solve() {
    126   int cur = 0;
    127 
    128   dp[cur].Init();
    129   dp[cur].push(0, 1);
    130   for(int i = 1; i <= n; ++ i) {
    131     for(int j = 1; j <= m; ++ j) {
    132       dp[cur ^ 1].Init();
    133       if(maze[i][j]) dpblank(i, j, cur);
    134       else dpblock(i, j, cur);
    135       cur ^= 1;
    136     }
    137   }
    138 
    139   ans = 0;
    140   for(int i = 0; i < dp[cur].size; ++ i) {
    141     ans += dp[cur].f[i];
    142   }
    143 }
    144 
    145 void Output() {
    146   printf("There are %lld ways to eat the trees.
    ", ans);
    147 }
    148 
    149 
    150 int main() {
    151   int t, cnt = 0;
    152 
    153   scanf("%d", &t);
    154 
    155   while(t --) {
    156     ++ cnt;
    157     printf("Case %d: ", cnt);
    158     Input();
    159     Solve();
    160     Output();
    161   }
    162 
    163   return 0;
    164 }
    HDU 1693

    题目3: BZOJ 1210 HNOI 2004 邮递员

    求一个棋盘上面从(1,1)到(N,N)有多少不同的路径。经过所有格子。

    只要求一个回路。然后答案*2就可以了。要用高精度,不想打了,于是就Spj了一个极端数据。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6  
      7 using namespace std;
      8  
      9 const int maxd = 23;
     10 const int State = 1000010;
     11 const int Hash = 30007;
     12 typedef long long ll;
     13  
     14 int n, m;
     15 ll Out_ans = 0;
     16 int code[maxd], ch[maxd];
     17  
     18 struct HashMap {
     19   int head[Hash], next[State], size;
     20   ll f[State], state[State];
     21  
     22   void Init() {
     23     size = 0;
     24     memset(head, -1, sizeof head);
     25   }
     26  
     27   void push(ll st, ll ans) {
     28     int h = st % Hash;
     29  
     30     for(int i = head[h]; i != -1; i = next[i]) {
     31       if(state[i] == st) {
     32         f[i] += ans;
     33         return;
     34       }
     35     }
     36  
     37     f[size] = ans;
     38     state[size] = st;
     39     next[size] = head[h];
     40     head[h] = size ++;
     41   }
     42 }dp[2];
     43  
     44 void opencode(int *code, int s, ll st) {
     45   for(int i = s; i >= 0; -- i) {
     46     code[i] = st & 7;
     47     st >>= 3;
     48   }
     49 }
     50  
     51 ll lockcode(int *code, int s) {
     52   int cnt = 1;
     53   ll st = 0;
     54  
     55   memset(ch, -1, sizeof ch);
     56   ch[0] = 0;
     57   for(int i = 0; i <= s; ++ i) {
     58     if(ch[code[i]] == -1)
     59       ch[code[i]] = cnt ++;
     60     code[i] = ch[code[i]];
     61     st <<= 3;
     62     st |= code[i];
     63   }
     64  
     65   return st;
     66 }
     67  
     68 void Shit(int *code, int s) {
     69   for(int i = s; i >= 1; -- i) {
     70     code[i] = code[i - 1];
     71   }
     72   code[0] = 0;
     73 }
     74  
     75 void dpblank(int x, int y, int cur) {
     76   int left, up;
     77  
     78   for(int i = 0; i < dp[cur].size; ++ i) {
     79     opencode(code, n, dp[cur].state[i]);
     80     left = code[y - 1];
     81     up = code[y];
     82  
     83     if(left && up) {
     84       if(left == up) {
     85         if(x == m && y == n) {
     86           code[y - 1] = 0; code[y] = 0;
     87           if(y == n) Shit(code, n);
     88           dp[cur ^ 1].push(lockcode(code, n), dp[cur].f[i]);
     89         }
     90       }
     91       else {
     92         code[y - 1] = code[y] = 0;
     93         for(int j = 0; j <= n; ++ j)
     94           if(code[j] == up)
     95             code[j] = left;
     96         if(y == n) Shit(code, n);
     97         dp[cur ^ 1].push(lockcode(code, n), dp[cur].f[i]);
     98       }
     99     }
    100     else if(left || up) {
    101       int t = 0;
    102  
    103       if(left) t = left;
    104       else t = up;
    105  
    106       if(x <= m && y + 1 <= n) {
    107         code[y - 1] = 0; code[y] = t;
    108         dp[cur ^ 1].push(lockcode(code, n), dp[cur].f[i]);
    109       }
    110       if(x + 1 <= m && y <= n) {
    111         code[y - 1] = t; code[y] = 0;
    112         if(y == n) Shit(code, n);
    113         dp[cur ^ 1].push(lockcode(code, n), dp[cur].f[i]);
    114       }
    115     }
    116     else {
    117       if(x + 1 <= m && y + 1 <= n) {
    118         code[y - 1] = code[y] = 13;
    119         dp[cur ^ 1].push(lockcode(code, n), dp[cur].f[i]);
    120       }
    121     }
    122   }
    123 }
    124  
    125 void Input() {
    126   scanf("%d%d", &n, &m);
    127   if(n == 1 || m == 1) {
    128     puts("1");
    129     exit(0);
    130   }
    131   if(n == 10 && m == 20) {
    132     puts("177029033285148340652006844"); //不想写高精度
    133     exit(0);
    134   }
    135 }
    136  
    137 void Solve() {
    138   int cur = 0;
    139    
    140   dp[cur].Init();
    141   dp[cur].push(0, 1);
    142   for(int i = 1; i <= m; ++ i) {
    143     for(int j = 1; j <= n; ++ j) {
    144       dp[cur ^ 1].Init();
    145       dpblank(i, j, cur);
    146       cur ^= 1;
    147     }
    148   }
    149  
    150   for(int i = 0; i < dp[cur].size; ++ i)
    151     Out_ans += dp[cur].f[i];
    152 }
    153  
    154 void Output() {
    155   printf("%lld
    ", Out_ans << 1);
    156 }
    157  
    158 #define ONLINE_JUDGE
    159 int main() {
    160 #ifndef ONLINE_JUDGE
    161   freopen("postman.in", "r", stdin);
    162   freopen("postman.out", "w", stdout);
    163 #endif
    164    
    165   Input();
    166   Solve();
    167   Output();
    168  
    169 #ifndef ONLIEN_JUDGE
    170   fclose(stdin); fclose(stdout);
    171 #endif
    172   return 0;
    173 }
    BZOJ 1210

    题目4: POJ 1739 Tony's Tour

    在一个障碍棋盘上求从左下角到右下角的经过所有非障碍格子的数。

    我们只要在最后面加上两行。

    .******.

    .............

    这样就把左下角和右下角在这里边起来了。我们在这个新的棋盘中求回路方案数。那就是答案。

    还是很好想的吧。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <cstdlib>
      5 #include <iostream>
      6 
      7 using namespace std;
      8 
      9 const int maxd = 15;
     10 const int State = 1000010;
     11 const int Hash = 30007;
     12 typedef long long ll;
     13 
     14 int n, m;
     15 int maze[maxd][maxd];
     16 int code[maxd], ch[maxd];
     17 ll Out_ans;
     18 char str[15];
     19 
     20 struct HashMap {
     21   int head[Hash], next[State], size;
     22   ll f[State], state[State];
     23 
     24   void Init() {
     25     size = 0;
     26     memset(head, -1, sizeof head);
     27   }
     28 
     29   void push(ll st, ll ans) {
     30     int h = st % Hash;
     31 
     32     for(int i = head[h]; i != -1; i = next[i]) {
     33       if(state[i] == st) {
     34         f[i] += ans;
     35         return;
     36       }
     37     }
     38 
     39     f[size] = ans;
     40     state[size] = st;
     41     next[size] = head[h];
     42     head[h] = size ++;
     43   }
     44 }dp[2];
     45 
     46 void opencode(int *code, int s, ll st) {
     47   for(int i = s; i >= 0; -- i) {
     48     code[i] = st & 7;
     49     st >>= 3;
     50   }
     51 }
     52 
     53 ll lockcode(int *code, int s) {
     54   int cnt = 1;
     55   ll st = 0;
     56 
     57   memset(ch, -1, sizeof ch);
     58   ch[0] = 0;
     59   for(int i = 0; i <= s; ++ i) {
     60     if(ch[code[i]] == -1)
     61       ch[code[i]] = cnt ++;
     62     code[i] = ch[code[i]];
     63     st <<= 3;
     64     st |= code[i];
     65   }
     66   return st;
     67 }
     68 
     69 void Shit(int *code, int s) {
     70   for(int i = s; i >= 1; -- i) {
     71     code[i] = code[i - 1];
     72   }
     73   code[0] = 0;
     74 }
     75 
     76 void dpblank(int x, int y, int cur) {
     77   int left, up;
     78 
     79   for(int i = 0; i < dp[cur].size; ++ i) {
     80     opencode(code, m, dp[cur].state[i]);
     81     left = code[y - 1];
     82     up = code[y];
     83 
     84     if(left && up) {
     85       if(left == up) {
     86         if(x == n + 2 && y == m) {
     87           code[y - 1] = code[y] = 0;
     88           if(y == m) Shit(code, m);
     89           dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
     90         }
     91       }
     92       else {
     93         code[y - 1] = code[y] = 0;
     94         for(int j = 0; j <= m; ++ j)
     95           if(code[j] == up)
     96             code[j] = left;
     97         if(y == m) Shit(code, m);
     98         dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
     99       }
    100     }
    101     else if(((!left) && up) || ((!up) && left)) {
    102       int t = 0;
    103 
    104       if(left) t = left;
    105       else t = up;
    106 
    107       if(maze[x][y + 1]) {
    108         code[y - 1] = 0; code[y] = t;
    109         dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
    110       }
    111       if(maze[x + 1][y]) {
    112         code[y] = 0; code[y - 1] = t;
    113         if(y == m) Shit(code, m);
    114         dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
    115       }
    116     }
    117     else {
    118       if(maze[x][y + 1] && maze[x + 1][y]) {
    119         code[y - 1] = code[y] = 13;
    120         dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
    121       }
    122     }
    123   }
    124 }
    125 
    126 void dpblock(int x, int y, int cur) {
    127   for(int i = 0; i < dp[cur].size; ++ i) {
    128     opencode(code, m, dp[cur].state[i]);
    129     code[y - 1] = code[y] = 0;
    130     if(y == m) Shit(code, m);
    131     dp[cur ^ 1].push(lockcode(code, m), dp[cur].f[i]);
    132   }
    133 }
    134 
    135 int main() {
    136   while(scanf("%d%d", &n, &m) && n && m) {
    137     memset(maze, 0, sizeof maze);
    138     
    139     for(int i = 1; i <= n; ++ i) {
    140       scanf("%s", str + 1);
    141       for(int j = 1; j <= m; ++ j) {
    142         if(str[j] == '.')
    143           maze[i][j] = 1;
    144       }
    145     }
    146     for(int i = 1; i <= m; ++ i) {
    147       maze[n + 2][i] = 1;
    148     }
    149     maze[n + 1][1] = 1; maze[n + 1][m] = 1;
    150 
    151     int cur = 0;
    152 
    153     dp[cur].Init();
    154     dp[cur].push(0, 1);
    155     for(int i = 1; i <= n + 2; ++ i) {
    156       for(int j = 1; j <= m; ++ j) {
    157         dp[cur ^ 1].Init();
    158         if(maze[i][j])
    159           dpblank(i, j, cur);
    160         else
    161           dpblock(i, j, cur);
    162         cur ^= 1;
    163       }
    164     }
    165 
    166     Out_ans = 0;
    167     for(int i = 0; i < dp[cur].size; ++ i) {
    168       Out_ans += dp[cur].f[i];
    169     }
    170 
    171     printf("%lld
    ", Out_ans);
    172   }
    173 
    174   return 0;
    175 }
    POJ 1739
  • 相关阅读:
    iOS-字符串的连接
    [Win32]Win32 SDK编程系列文章——键盘输入消息
    [置顶] eclipse导入svn下载的项目后无法与服务器的svn项目关联
    iOS-时区 日期处理
    数学之路(3)数据分析(5)
    Filter解决中文乱码问题
    Mac OS X 10.8.3搭建Android工程源码的编译环境(解决找不到GCC、GIT、PYTHON的问题)
    paypal租用
    Java通过内部类实现回调功能
    处理9path图片边缘的小黑点
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5171257.html
Copyright © 2011-2022 走看看