题目链接: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 }
时间: 2024-10-15 12:25:09