标签:
原题网址:http://acm.timus.ru/problem.aspx?space=1&num=1519
详细代码(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 }
标签:
原文地址:http://www.cnblogs.com/yyf2016/p/5753117.html