码迷,mamicode.com
首页 > 其他好文 > 详细

Ural1519 Formula 1(插头dp)

时间:2016-08-09 14:59:08      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

原题网址:http://acm.timus.ru/problem.aspx?space=1&num=1519

有关插头dp和状态压缩请参考:
http://wenku.baidu.com/link?url=AFuYe_EfR5yXMNK0rY-TaLe6LLgKhsOVxBM1RQULxElPrvjQVlO724nUxlXtaDx4aLp7FHIz8AexYiTy06_r4CV5XUs6c9lM5vpz5kDr6HG

详细代码(c++):

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 // using namespace std;
  5 
  6 typedef long long LL;
  7 const int MAXRC = 15, MAXSTATE=300001;
  8 int m,n,er=-1,ec, idx=0;
  9 int city[MAXRC][MAXRC]={0}, bits_at[MAXRC];// 1 is valid.
 10 
 11 class Hashmap{
 12 public:
 13     int head[MAXSTATE], nxt[MAXSTATE], size;
 14     LL state[MAXSTATE], num[MAXSTATE];
 15     void init(){
 16         size = 0;
 17         memset(head, -1, sizeof head);
 18         // memset(nxt, -1, sizeof nxt);// 头插法不用初始化nxt
 19     }
 20     void push(LL s, LL n){
 21         int pos = s%MAXSTATE, bg = head[pos];
 22         while(bg != -1){
 23             if(state[bg]==s){
 24                 num[bg] += n;
 25                 return ;
 26             }
 27             bg = nxt[bg];
 28         }
 29         state[size] = s;
 30         num[size] = n;
 31         // 头插法
 32         nxt[size] = head[pos];
 33         head[pos] = size++;
 34     }
 35 }hm[2];
 36 
 37 inline int get_state_at(LL s, int j){
 38     return (s&bits_at[j])>>(j<<1);
 39 }
 40 inline LL set_state_at(LL s, int j, int b){
 41     s &= ~(bits_at[j]);
 42     return s|(b<<(j<<1));
 43 }
 44 inline LL set_state_at(LL s, int j, int bj, int bn){
 45     s &= ~(bits_at[j]+bits_at[j+1]);
 46     s |= (bj+(bn<<2))<<(j<<1);
 47     return s;
 48 }
 49 int find_match(LL s, int j){// c!=0
 50     int c = get_state_at(s, j), d = c == 1? 1:-1, f = 0;
 51     for(;;j+=d){
 52         if(get_state_at(s, j)==c) f++;
 53         else if(get_state_at(s,j)) f--;
 54         if(f == 0) return j;
 55     }
 56     return -1;
 57 }
 58 void dp(){
 59     idx = 0;hm[idx].init();hm[idx].push(0,1);
 60     for(int i=0; i<n; ++i){
 61         for(int j=0; j<hm[idx].size; ++j)
 62             hm[idx].state[j] <<= 2;// 最右位一定为0
 63         for(int j=0; j<m; ++j){
 64             int cur = idx^1;// 滚动数组,要求的状态集
 65             hm[cur].init();
 66             for(int k=0; k<hm[idx].size; ++k){
 67                 LL ps = hm[idx].state[k], pn = hm[idx].num[k];
 68                 int sl = get_state_at(ps, j), su = get_state_at(ps, j+1);
 69                 if(sl == 0 && su == 0){
 70                     if(!city[i][j]){// 将状态延伸到非 . 处
 71                         hm[cur].push(set_state_at(ps, j, 0, 0), pn);
 72                     }// 插头应该指向空白的格子
 73                     else if(city[i][j+1] && city[i+1][j]){
 74                         hm[cur].push(set_state_at(ps, j, 1, 2), pn);
 75                     }
 76                 }
 77                 // else if(!city[i][j]) continue;// 此处不会执行
 78                 else if(sl == 0 || su == 0){// 只延伸一个插头
 79                     if(city[i][j+1]) hm[cur].push(set_state_at(ps, j, 0, sl+su), pn);
 80                     if(city[i+1][j])
 81                         hm[cur].push(set_state_at(ps, j, sl+su, 0), pn); 
 82                 }
 83                 else if(sl == su){// 合并连通块,同时左括号或右括号
 84                     int posl = find_match(ps, j), posu = find_match(ps, j+1);
 85                     int mn = std::min(posl, posu), mx = std::max(posl, posu);
 86                     LL cs = set_state_at(ps, mn, 1);
 87                     cs = set_state_at(cs, mx, 2);
 88                     hm[cur].push(set_state_at(cs, j, 0, 0), pn);
 89                 }
 90                 else if(sl == 2 && su == 1){// 合并成简单路径
 91                     hm[cur].push(set_state_at(ps, j, 0, 0), pn);
 92                 }
 93                 else if(i == er && j == ec){// 合并成回路,只在最后一个有效的格子
 94                     hm[cur].push(set_state_at(ps, j, 0, 0), pn);
 95                 }
 96             }
 97             idx = cur;// 交换状态    
 98         }
 99     }
100 }
101 int main(){
102     freopen("in.txt", "r", stdin);
103     scanf("%d%d", &n, &m);
104     char cy[MAXRC][MAXRC];
105     for(int i=0; i<n; ++i){
106         scanf("%s", cy[i]);
107         for(int j=0; j<m; ++j){
108             if(cy[i][j] == .){
109                 city[i][j] = 1;
110                 er = i; ec = j;
111             }
112         }
113     }
114     for(int i=0; i<=m; ++i){
115         bits_at[i] = 3<<(i<<1);// 0 is invalid, 1 is left bracket, 2 is right bracket.
116     }
117     dp();
118     printf("%lld\n", hm[idx].size>0?hm[idx].num[0]:0LL);
119     return 0;
120 }

 

Ural1519 Formula 1(插头dp)

标签:

原文地址:http://www.cnblogs.com/yyf2016/p/5753117.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!