题目大意:
找到多条回路覆盖所有非障碍格子,问这样回路的种数
这里的插头与URAL1519 不一样的是 只要管它是否存在即可,只需要1个二进制位表示状态
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 ; 12 int code[MAXD] , mp[MAXD][MAXD]; 13 14 struct HASHMAP{ 15 int head[HASH] , next[STATE] , state[STATE] , size; 16 ll f[STATE]; 17 18 void init(){ 19 size = 0; 20 memset(head , -1 , sizeof(head)); 21 } 22 23 void push_in(int st , ll sum){ 24 int h = st%HASH; 25 for(int i = head[h] ; ~i ; i=next[i]){ 26 if(st == state[i]){ 27 f[i]+=sum; 28 return ; 29 } 30 } 31 f[size]=sum; 32 state[size] = st; 33 next[size] = head[h]; 34 head[h] = size++; 35 } 36 }hashmap[2]; 37 38 void decode(int *code , int m , int st) 39 { 40 for(int i=m ; i>=0 ; i--){ 41 code[i] = st&1; 42 st>>=1; 43 } 44 } 45 46 int encode(int *code , int m) 47 { 48 int st=0; 49 for(int i=0 ; i<=m ; i++){ 50 st<<=1; 51 st |= code[i]; 52 } 53 return st; 54 } 55 56 void init() 57 { 58 scanf("%d%d" , &n , &m); 59 for(int i=1 ; i<=n ; i++){ 60 for(int j=1 ; j<=m ; j++){ 61 scanf("%d" , &mp[i][j]); 62 } 63 } 64 } 65 66 void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧 67 { 68 for(int i=m ; i>=0 ; i--) code[i] = code[i-1]; 69 code[0] = 0; 70 } 71 72 void dpblank(int i , int j , int cur) //处理可执行格子 73 { 74 // cout<<"ok: "<<i<<" "<<j<<endl; 75 int k , left , up; 76 for(k=0 ; k<hashmap[cur].size ; k++){ 77 decode(code , m , hashmap[cur].state[k]); 78 left = code[j-1]; 79 up = code[j]; 80 if(left&&up){ //插头均存在 1 1 81 code[j-1] = code[j] = 0; 82 if(j == m) shift(code , m); 83 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 84 // cout<<i<<" "<<j<<" "<<encode(code , m)<<" "<<hashmap[cur].f[k]<<endl; 85 } 86 else if(left || up){ // 1 || 1 87 if(j<m && mp[i][j+1]){ 88 //这里面右插头是可选的,所以不存在换行shift() 89 code[j-1] = 0 , code[j] = 1; 90 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 91 } 92 if(i<n && mp[i+1][j]){ 93 code[j-1] = 1 , code[j] = 0; 94 if(j == m) shift(code , m); 95 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 96 } 97 } 98 else { 99 if((j<m && mp[i][j+1]) && (i<n && mp[i+1][j])){ 100 code[j-1] = code[j] = 1; 101 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 102 } 103 } 104 } 105 } 106 107 void dpblock(int i , int j , int cur) 108 { 109 // cout<<"flase: "<<i<<" "<<j<<endl; 110 int k , left , up; 111 for(k=0 ; k<hashmap[cur].size ; k++){ 112 decode(code , m , hashmap[cur].state[k]); 113 left = code[j-1] , up = code[j]; 114 if(j == m) shift(code , m); 115 if(left+up == 0) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]); 116 } 117 } 118 119 ll solve() 120 { 121 ll ans = 0; 122 int cur = 0; 123 hashmap[cur].init(); 124 hashmap[cur].push_in(0 , 1); 125 for(int i=1 ; i<=n ; i++){ 126 for(int j=1 ; j<=m ; j++){ 127 hashmap[cur^1].init(); 128 if(mp[i][j]) dpblank(i , j , cur); 129 else dpblock(i , j , cur); 130 cur ^= 1; 131 } 132 } 133 for(int i=0 ; i<hashmap[cur].size ; i++) 134 ans += hashmap[cur].f[i]; 135 return ans; 136 } 137 138 int main() 139 { 140 // freopen("in.txt" , "r" , stdin); 141 int T , cas=0; 142 scanf("%d" , &T); 143 while(T--) 144 { 145 init(); 146 printf("Case %d: There are %I64u ways to eat the trees.\n" , ++cas , solve()); 147 } 148 return 0; 149 }
我还在坚持,我还未达到我所想,梦~~一直在