题目大意:

找到多条回路覆盖所有非障碍格子,问这样回路的种数

这里的插头与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 }

 

 posted on 2015-08-12 19:27  Love风吟  阅读(386)  评论(0编辑  收藏  举报