楼教主男人八题之一。。。
题目大意:
求从左下角经过所有非障碍点一次到达右下角的方案数
这里不是求回路,但是我们可以考虑,在最下面一行再增加一行,那么就可以当做求此时左下角到右下角的回路总数,那么就转化成了陈丹琦论文的URAL1519的
方法了
但是最后一行添加的格子必须是最后一条直线跑的,也就是除了左下角和右下角中间的点只能有水平方向上的插头
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 6 using namespace std; 7 #define ll 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 bool flag[MAXD][MAXD];//标记位,标记当前点能否作为最终点 14 ll ans = 0; 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 int num = 0;//记录共有的插头数量 40 void decode(int *code , int m , int st) 41 { 42 num = 0; 43 for(int i=m ; i>=0 ; i--){ 44 code[i] = st&3; 45 st>>=2; 46 if(code[i]) num++; 47 } 48 } 49 50 int encode(int *code , int m) 51 { 52 int st=0; 53 for(int i=0 ; i<=m ; i++){ 54 st<<=2; 55 st |= code[i]; 56 } 57 return st; 58 } 59 60 void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧 61 { 62 for(int i=m ; i>=0 ; i--) code[i] = code[i-1]; 63 code[0] = 0; 64 } 65 66 void dpblank(int i , int j , int cur) 67 { 68 int k , left , up; 69 for(k=0 ; k<hashmap[cur].size ; k++){ 70 decode(code , m , hashmap[cur].state[k]); 71 left = code[j-1]; 72 up = code[j]; 73 // cout<<"chatou: "<<i<<" "<<j<<" "<<left<<" "<<up<<endl; 74 if(!left && !up){ 75 if(mp[i][j+1] && mp[i-1][j]){ //不断向上转移 76 code[j-1] = 1 , code[j] = 2; 77 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 78 } 79 } 80 else if(!left && up){ 81 if(mp[i][j+1]) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 82 if(mp[i-1][j]){ 83 code[j-1] = up , code[j] = 0; 84 if(j == m) shift(code , m); 85 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 86 } 87 } 88 else if(left && !up){ 89 if(mp[i-1][j]){ 90 if(j == m) shift(code , m); 91 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 92 } 93 if(mp[i][j+1]){ 94 code[j-1] = 0 , code[j] = left; 95 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 96 } 97 } 98 else if(left==1 && up == 1){ 99 int cnt = 1; 100 for(int v=j+1 ; v<=m ; v++){ 101 if(code[v]==1)cnt++; 102 if(code[v]==2)cnt--; 103 if(!cnt){ 104 code[v]=1; 105 break; 106 } 107 } 108 code[j-1] = code[j] = 0; 109 if(j == m) shift(code , m); 110 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 111 } 112 else if(left == 2 && up == 2){ 113 int cnt=1; 114 for(int v=j-2 ; v>=1 ; v--){ 115 if(code[v]==2)cnt++; 116 if(code[v]==1)cnt--; 117 if(!cnt){ 118 code[v]=2; 119 break; 120 } 121 } 122 code[j-1] = code[j] = 0; 123 if(j == m) shift(code , m); 124 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 125 } 126 else if(left==1 && up==2){ 127 if(i==enx && j==eny) { 128 code[j-1] = code[j] = 0; 129 if(j == m) shift(code , m); 130 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 131 } 132 } 133 else{ 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 } 139 } 140 141 void dpblock(int i , int j , int cur) 142 { 143 int k , left , up; 144 for(k=0 ; k<hashmap[cur].size ; k++){ 145 decode(code , m , hashmap[cur].state[k]); 146 left = code[j-1]; 147 up = code[j]; 148 // cout<<"block: "<<i<<" "<<j<<" "<<left<<" "<<up<<endl; 149 if(!left && !up){ 150 if(j==m) shift(code , m); 151 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 152 153 } 154 } 155 } 156 157 void dpselect(int i , int j , int cur) 158 { 159 int k , left , up; 160 for(k=0 ; k<hashmap[cur].size ; k++){ 161 decode(code , m , hashmap[cur].state[k]); 162 left = code[j-1]; 163 up = code[j]; 164 if(left==2 && !up){ 165 code[j-1] = 0 , code[j] = 2; 166 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 167 } 168 } 169 } 170 171 char s[MAXD][MAXD]; 172 173 void init() 174 { 175 for(int i=1 ; i<=n ; i++){ 176 scanf("%s" , s[i]+1); 177 for(int j=1 ; j<=m ; j++){ 178 mp[i][j] = s[i][j]==‘.‘; 179 } 180 } 181 for(int i=n ; i>=1 ; i--) 182 for(int j=1 ; j<=m ; j++) 183 if(mp[i][j]) enx=i , eny=j; 184 mp[n+1][1] = 1 , mp[n+1][m] = 1; 185 for(int i=2 ; i<m ; i++) mp[n+1][i] = 2; 186 n++; 187 for(int i=1 ; i<=m+1 ; i++) mp[0][i] = 0; 188 for(int i=0 ; i<=n ; i++) mp[i][m+1] = 0; 189 /* for(int i=0 ; i<=n ; i++) 190 { 191 for(int j=1 ; j<=m+1 ; j++){ 192 cout<<mp[i][j]<<" "; 193 } 194 cout<<endl; 195 } 196 cout<<enx<<" "<<eny<<endl;*/ 197 } 198 199 ll solve() 200 { 201 ans = 0; 202 int cur = 0; 203 hashmap[cur].init(); 204 hashmap[cur].push_in(0 , 1); 205 for(int i=n ; i>=1 ; i--){ 206 for(int j=1 ; j<=m ; j++){ 207 hashmap[cur^1].init(); 208 if(mp[i][j]==1) dpblank(i , j , cur); 209 else if(mp[i][j]==0) dpblock(i , j , cur); 210 else dpselect(i , j , cur); 211 cur^=1; 212 } 213 214 } 215 for(int i=0 ; i<hashmap[cur].size ; i++) ans+=hashmap[cur].f[i]; 216 return ans; 217 } 218 219 int main() 220 { 221 // freopen("in.txt" , "r" , stdin); 222 int cas = 0; 223 while(scanf("%d%d" , &n , &m) , n+m) 224 { 225 init(); 226 // printf("Case %d: ",++cas); 227 if(n==1 && m==1){ 228 printf("%d\n" , 1); 229 continue; 230 } 231 printf("%I64d\n" , solve()); 232 } 233 return 0; 234 }
时间: 2024-10-29 18:33:50