题目大意:
给定一个图,一部分点'*'作为障碍物,求经过所有非障碍点的汉密尔顿回路有多少条
基础的插头DP题目,对于陈丹琦的论文来说我觉得http://blog.sina.com.cn/s/blog_51cea4040100gmky.html
这个博客写的更容易理解,不过好像这篇博客里的代码有问题,反正是A不了题目的
不过上面的图和思路写的很清楚,可以作为参考
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define ll unsigned long long const int HASH_SIZE = 199917; bool mp[15][15]; char str[15][15]; int n, m , k , nn , mm; int tot[2] , bit[15] , hash[HASH_SIZE] , state[2][HASH_SIZE]; ll dp[2][HASH_SIZE] , ans; void init() { //每一位用4进制保存,那么对于每一个状态来说都是右移2次,所以这里i*2 for(int i=0 ; i<=13 ; i++) bit[i] = i<<1; memset(dp , 0 , sizeof(dp)); tot[0] = dp[0][1] = 1 , ans = k = 0; state[0][1] = 0; } void hash_in(int s , ll sum)//s表示当前状态,sum是指s状态下共有sum种方式形成 { // print(s); // cout<<" "<<sum<<endl; int p = s%HASH_SIZE; while(hash[p]){ if(state[k][hash[p]] == s){ dp[k][hash[p]] += sum; return ; } p++; if(p == HASH_SIZE) p=0; } hash[p] = ++tot[k]; state[k][hash[p]] = s; dp[k][hash[p]] = sum; } void work() { for(int i=1 ; i<=n ; i++){ for(int j=1 ; j<=m ; j++){ k^=1 ; //滚动数组 tot[k] = 0; memset(hash , 0 , sizeof(hash)); for(int u=1 ; u<=tot[1-k] ; u++){ int s = state[1-k][u] , curs; ll sum = dp[1-k][u]; int p = (s>>bit[j-1])&3 , q = (s>>bit[j])&3; //3进制 , 用( , # , )来理解 if(!mp[i][j]){ if(p==0 && q==0) hash_in(s , sum); } else{ if(p == 0 && q == 0){ if(!mp[i+1][j] || !mp[i][j+1]) continue; curs = s + (1<<bit[j-1]) + (2<<bit[j]); hash_in(curs , sum); } else if(!p && q){ if(mp[i][j+1]) hash_in(s , sum); if(mp[i+1][j]){ curs = s+q*(1<<bit[j-1])-q*(1<<bit[j]); hash_in(curs , sum); } } else if(p && !q){ if(mp[i+1][j]) hash_in(s , sum); if(mp[i][j+1]){ curs = s - p*(1<<bit[j-1])+p*(1<<bit[j]); hash_in(curs , sum); } } else if(p+q==2){ //可理解为p==1 && q==1 int cnt = 1; for(int v=j+1 ; v<=m ; v++){ int w = (s>>bit[v])&3; if(w == 1) cnt++; if(w == 2) cnt--; if(!cnt){ curs = s-(1<<bit[v]); //将)转化为( ->状态由2->1 , 减少了一个 break; } } curs = curs-(1<<bit[j])-(1<<bit[j-1]); hash_in(curs , sum); } else if(p+q==4){//可理解为p==2 && q==2 int cnt = 1; for(int v=j-2 ; v>=1 ; v--){ int w = (s>>bit[v])&3; if(w == 1) cnt--; if(w == 2) cnt++; if(!cnt){ curs= s+(1<<bit[v]); break; } } curs = curs-(2<<bit[j])-(2<<bit[j-1]); hash_in(curs , sum); } else if(p==1 && q==2){ if(i==nn && j==mm) ans+=sum; } else if(p==2 && q==1){ curs = s-(2<<bit[j-1])-(1<<bit[j]); hash_in(curs , sum); } } } } for(int j=1 ; j<=tot[k] ; j++) state[k][j]<<=2; } printf("%lld\n" , ans); } int main() { // freopen("in.txt" , "r" , stdin); while(~scanf("%d%d" , &n , &m)) { memset(mp , 0 , sizeof(mp)); for(int i=1 ; i<=n ; i++){ scanf("%s" , str[i]+1); for(int j=1 ; j<=m ; j++){ mp[i][j] = str[i][j]=='.'; // if(mp[i][j]) cout<<i<<" "<<j<<endl; if(mp[i][j]) nn=i , mm=j;//记录最后一个可执行块 } } init(); work(); } return 0; }
后来写hdu上的题目的时候觉得kuangbin的表达方式还是很清晰的,所以又将源代码修改成了:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 #define ll unsigned long long 8 const int HASH = 10007; 9 const int STATE = 1000010; 10 const int MAXD = 15; 11 int n , m , enx , eny; 12 int code[MAXD] , mp[MAXD][MAXD]; 13 ll ans = 0; 14 15 struct HASHMAP{ 16 int head[HASH] , next[STATE] , state[STATE] , size; 17 ll f[STATE]; 18 19 void init(){ 20 size = 0; 21 memset(head , -1 , sizeof(head)); 22 } 23 24 void push_in(int st , ll sum){ 25 int h = st%HASH; 26 for(int i = head[h] ; ~i ; i=next[i]){ 27 if(st == state[i]){ 28 f[i]+=sum; 29 return ; 30 } 31 } 32 f[size]=sum; 33 state[size] = st; 34 next[size] = head[h]; 35 head[h] = size++; 36 } 37 }hashmap[2]; 38 39 void decode(int *code , int m , int st) 40 { 41 for(int i=m ; i>=0 ; i--){ 42 code[i] = st&3; 43 st>>=2; 44 } 45 } 46 47 int encode(int *code , int m) 48 { 49 int st=0; 50 for(int i=0 ; i<=m ; i++){ 51 st<<=2; 52 st |= code[i]; 53 } 54 return st; 55 } 56 57 void init() 58 { 59 char str[MAXD][MAXD]; 60 for(int i=1 ; i<=n ; i++){ 61 scanf("%s" , str[i]+1); 62 for(int j=1 ; j<=m ; j++){ 63 if(str[i][j] == '.'){ 64 mp[i][j] = 1; 65 enx = i , eny = j; 66 }else mp[i][j] = 0; 67 } 68 mp[i][m+1]=0; 69 mp[n+1][i] = 0; 70 } 71 } 72 73 void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧 74 { 75 for(int i=m ; i>=0 ; i--) code[i] = code[i-1]; 76 code[0] = 0; 77 } 78 79 void dpblank(int i , int j , int cur) //处理可执行格子 80 { 81 // cout<<"ok: "<<i<<" "<<j<<endl; 82 int k , left , up; 83 for(k=0 ; k<hashmap[cur].size ; k++){ 84 decode(code , m , hashmap[cur].state[k]); 85 left = code[j-1]; 86 up = code[j]; 87 if(!left && !up){ 88 if(!mp[i][j+1] || !mp[i+1][j]) continue; 89 code[j-1] = 1 , code[j] = 2; 90 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 91 } 92 else if(!left && up){ 93 if(mp[i][j+1]) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 94 if(mp[i+1][j]){ 95 code[j-1] = up , code[j] = 0; 96 if(j == m) shift(code , m); 97 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 98 } 99 } 100 else if(left && !up){ 101 if(mp[i+1][j]){ 102 if(j == m) shift(code , m); 103 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 104 } 105 if(mp[i][j+1]){ 106 code[j-1] = 0 , code[j] = left; 107 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 108 } 109 } 110 else if(left==1 && up == 1){ 111 int cnt = 1; 112 for(int v=j+1 ; v<=m ; v++){ 113 if(code[v]==1)cnt++; 114 if(code[v]==2)cnt--; 115 if(!cnt){ 116 code[v]=1; 117 break; 118 } 119 } 120 code[j-1] = code[j] = 0; 121 if(j == m) shift(code , m); 122 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 123 } 124 else if(left == 2 && up == 2){ 125 int cnt=1; 126 for(int v=j-2 ; v>=1 ; v--){ 127 if(code[v]==2)cnt++; 128 if(code[v]==1)cnt--; 129 if(!cnt){ 130 code[v]=2; 131 break; 132 } 133 } 134 code[j-1] = code[j] = 0; 135 if(j == m) shift(code , m); 136 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 137 } 138 else if(left==1 && up==2){ 139 if(i==enx && j==eny) ans+=hashmap[cur].f[k]; 140 } 141 else{ 142 code[j-1]=code[j]=0; 143 if(j == m) shift(code , m); 144 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 145 } 146 } 147 } 148 149 void dpblock(int i , int j , int cur) 150 { 151 // cout<<"flase: "<<i<<" "<<j<<endl; 152 int k , left , up; 153 for(k=0 ; k<hashmap[cur].size ; k++){ 154 decode(code , m , hashmap[cur].state[k]); 155 left = code[j-1] , up = code[j]; 156 if(!left && !up){ 157 if(j == m) shift(code , m); 158 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 159 } 160 } 161 } 162 163 ll solve() 164 { 165 ans = 0; 166 int cur = 0; 167 hashmap[cur].init(); 168 hashmap[cur].push_in(0 , 1); 169 for(int i=1 ; i<=n ; i++){ 170 for(int j=1 ; j<=m ; j++){ 171 hashmap[cur^1].init(); 172 if(mp[i][j]) dpblank(i , j , cur); 173 else dpblock(i , j , cur); 174 cur ^= 1; 175 } 176 } 177 return ans; 178 } 179 180 int main() 181 { 182 // freopen("in.txt" , "r" , stdin); 183 while(~scanf("%d%d" , &n , &m)) 184 { 185 init(); 186 printf("%I64d\n" , solve()); 187 } 188 return 0; 189 }
我还在坚持,我还未达到我所想,梦~~一直在