zoukankan      html  css  js  c++  java
  • Ural 1519 Formula 1 插头DP

      这是一道经典的插头DP单回路模板题。

      用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制。

      1、当同时存在左、上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连;若不相同,则把这两个连通块连起来。

      2、如果只存在左或上插头的时候,则要延续连通块。

      3、若都不存在左和上插头的时候,就要新建一个连通块。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <string>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
     10 #define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i)
     11 #define mset(a, b) memset(a, b, sizeof(a))
     12 typedef long long LL;
     13 const int MAXD = 15, HASH = 30007, STATE = 100010;
     14 int n, m, maze[MAXD][MAXD], code[MAXD], ch[MAXD], end_x, end_y;
     15 char str[MAXD];
     16 struct HASHMAP
     17 {
     18     int head[HASH], nxt[STATE], siz; LL f[STATE], state[STATE];
     19     void clear() { siz = 0, mset(head, -1); }
     20     void push(LL x, LL add)
     21     {
     22         int pos = x%HASH, i = head[pos];
     23         for (; i != -1; i = nxt[i])
     24             if (state[i] == x) { f[i] += add; return ; }
     25         state[siz] = x, f[siz] = add;
     26         nxt[siz] = head[pos], head[pos] = siz++;
     27     }
     28 }hm[2];
     29 
     30 void in()
     31 {
     32     scanf("%d %d", &n, &m), mset(maze, 0), end_x = end_y = -1;
     33     REP(i, 1, n)
     34     {
     35         scanf("%s", str+1);
     36         REP(j, 1, m) 
     37             if (str[j] == '.')
     38                 maze[i][j] = 1, end_x = i, end_y = j;
     39     }
     40 }
     41 
     42 void decode(LL x)
     43 {
     44     REP(i, 0, m) code[i] = x&7, x >>= 3;
     45 }
     46 
     47 LL encode()
     48 {
     49     LL ret = 0; int cnt = 0;
     50     mset(ch, -1), ch[0] = 0;
     51     DWN(i, m, 0) 
     52     {
     53         if (ch[code[i]] == -1) ch[code[i]] = ++cnt;
     54         ret <<= 3, ret |= ch[code[i]];
     55     }
     56     return ret;
     57 }
     58 
     59 void shift(int j)
     60 {
     61     if (j != m) return ;
     62     DWN(i, m, 1) code[i] = code[i-1];
     63     code[0] = 0;
     64 }
     65 
     66 void dp_blank(int i, int j, int cur)
     67 {
     68     REP(k, 0, hm[cur].siz-1)
     69     {
     70         decode(hm[cur].state[k]);
     71         int lef = code[j-1], up = code[j];
     72         if (lef && up)
     73         {
     74             if (lef == up && !(i == end_x && j == end_y)) continue ;
     75             REP(t, 0, m)
     76                 if (code[t] == up) code[t] = lef;
     77             code[j-1] = code[j] = 0, shift(j);
     78             hm[cur^1].push(encode(), hm[cur].f[k]);
     79         }
     80         else
     81             if (lef || up)
     82             {
     83                 int t = lef ? lef : up;
     84                 if (maze[i][j+1])
     85                 {
     86                     code[j-1] = 0, code[j] = t;
     87                     hm[cur^1].push(encode(), hm[cur].f[k]);
     88                 }
     89                 if (maze[i+1][j])
     90                 {
     91                     code[j-1] = t, code[j] = 0, shift(j);
     92                     hm[cur^1].push(encode(), hm[cur].f[k]);
     93                 }
     94             }
     95             else
     96                 if (maze[i][j+1] && maze[i+1][j])
     97                 {
     98                     code[j-1] = code[j] = 13, shift(j);
     99                     hm[cur^1].push(encode(), hm[cur].f[k]);
    100                 }
    101     }
    102 }
    103 
    104 void dp_block(int i, int j, int cur)
    105 {
    106     REP(k, 0, hm[cur].siz-1)
    107     {
    108         decode(hm[cur].state[k]), shift(j);
    109         hm[cur^1].push(encode(), hm[cur].f[k]);
    110     }
    111 }
    112 
    113 void work()
    114 {
    115     int cur = 0; LL ans = 0;
    116     hm[0].clear(), hm[1].clear(), hm[cur].push(0, 1);
    117     REP(i, 1, n)
    118         REP(j, 1, m)
    119         {
    120             if (maze[i][j]) dp_blank(i, j, cur);
    121             else dp_block(i, j, cur);
    122             hm[cur].clear(), cur ^= 1;
    123         }
    124     REP(i, 0, hm[cur].siz-1) ans += hm[cur].f[i];
    125     printf("%I64d
    ", ans);
    126 }
    127 
    128 int main()
    129 {
    130     in();
    131     work();
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    centos7刚安装解决网络问题
    python matplotlib的常用绘图方法
    python实现最小可编辑距离
    JDBC快速入门
    关于MYSQL常用操作查询语言
    3w字详解java集合
    ELK实时日志分析平台环境部署--完整记录(转)
    ELK简介(转)
    python格式化输出(% & format)
    ElasticSearch查询 搜索 | 更新 | 查询
  • 原文地址:https://www.cnblogs.com/-ZZB-/p/6435074.html
Copyright © 2011-2022 走看看