ZOJ 3209 Treasure Map

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3209

dancing links 每个点作为一列。

每个块作为一行。

 

不知道为什么插节点的时候 如果把循环写成

for(int i = y1+1; i <= y2; i++){      //行 
              for(int j = x1+1; j <= x2; j++){ //列 
      
              }
          }
然后col = (y-1)*n+x就会超时。

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <string>
  5 #include <iomanip>
  6 using namespace std;
  7 int T, n, m, p, x1, y1, x2, y2;
  8 #define maxn 510*35*35
  9 int R[maxn], L[maxn], U[maxn], D[maxn];
 10 int H[maxn], C[maxn], colsum[999];
 11 int head, cnt, ans;
 12 void addnode(int i, int j, int h, int rowhead, int sum, int pre){
 13     int col = j+(i-1)*m; //cout<<col<<" ";
 14     cnt++;
 15     
 16     H[cnt] = h; C[cnt] = col;
 17     if(sum == 1){
 18         R[cnt] = cnt; L[cnt] = cnt;
 19     }
 20     else if(sum == 2){
 21         R[pre] = cnt; R[cnt] = pre;
 22         L[pre] = cnt; L[cnt] = pre; 
 23     }
 24     else{
 25         R[cnt] = rowhead; R[pre] = cnt;
 26         L[cnt] = pre; L[rowhead] = cnt;
 27     }
 28     
 29     D[U[col]] = cnt;
 30     U[cnt] = U[col];
 31     D[cnt] = col;
 32     U[col] = cnt;
 33     
 34     colsum[col]++; 
 35     
 36 }
 37 void init(){
 38     head = cnt = 0;
 39     ans = 510;  //最多就是500块。 
 40     R[head] = 1; L[head] = n*m; U[head] = head; D[head] = head;
 41     H[head] = 0; C[head] = 0;
 42     memset(colsum, 0, sizeof(colsum));
 43     for(int i = 1; i <= n*m; i++){
 44         cnt++;
 45         U[cnt] = D[cnt] = cnt;
 46         H[cnt] = 0; C[cnt] = i;
 47         if(i == n*m){
 48             R[cnt-1] = cnt; L[cnt] = cnt-1; R[cnt] = head;
 49         }    
 50         else{
 51             R[cnt-1] = cnt; L[cnt] = cnt-1;    
 52         }
 53     }
 54     for(int cc = 1; cc <= p; cc++){
 55         scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
 56         int sum = 0, rowhead = -1, pre;
 57         for(int i = x1+1; i <= x2; i++){      //
 58             for(int j = y1+1; j <= y2; j++){ //
 59                 sum++;
 60                 addnode(i, j ,cc, rowhead, sum, pre);
 61                 if(rowhead == -1) rowhead = cnt;
 62                 pre = cnt;
 63             }
 64         }
 65     }
 66 }
 67 void remove(int c){
 68     R[L[c]] = R[c]; L[R[c]] = L[c];
 69     for(int i = D[c]; i != c; i = D[i]){
 70         for(int j = R[i]; j != i; j = R[j]){
 71             U[D[j]] = U[j]; D[U[j]] = D[j];
 72             colsum[C[j]]--;
 73         }
 74     }
 75 }
 76 void resume(int c){
 77     R[L[c]] = c; L[R[c]] = c;
 78     for(int i = D[c]; i != c; i = D[i]){
 79         for(int j = R[i]; j != i; j = R[j]){
 80             U[D[j]] = j; D[U[j]] = j;
 81             colsum[C[j]]++;
 82         }
 83     }
 84 }
 85 void dance(int k){
 86     if(k >= ans) return;
 87     int c = R[head];
 88     if(c == head){
 89         ans = k;
 90         return;
 91     }
 92     int min = 9999999;
 93     for(int i = R[head]; i != head; i = R[i]){
 94         if(colsum[i] <= min){
 95             min = colsum[i]; c = i;
 96         }
 97     }
 98     remove(c);
 99     for(int i = D[c]; i != c; i = D[i]){
100         for(int j = R[i]; j != i; j = R[j]) remove(C[j]);
101         dance(k+1);
102         for(int j = L[i]; j != i; j = L[j]) resume(C[j]); //要写成L 
103     }
104     resume(c);
105     return ;
106 }
107 int main(){
108     scanf("%d", &T);
109     while(T--){
110         scanf("%d%d%d", &n, &m, &p); //n是列,m是行。 
111         init();
112         dance(0);
113         if(ans == 510) printf("-1\n");
114         else printf("%d\n", ans);
115     }
116     
117     return 0;
118 }

 

posted @ 2015-04-24 00:54  下周LGD该赢了吧  阅读(140)  评论(0编辑  收藏  举报