ZOJ - 3209 Treasure Map

Dance Linking

 

很早就想写下Dance Linking了。那个时候用一般的搜索方法解了数独。之后在网上看到说能用 Knuth 发明的 Dance Linking 高效地解决。所以找了一些资料来看(当然也包括momodi的《Dancing Links 在搜索中的应用》)。最后看懂了,但是不知道怎么构造这个十字链表 T_T 。后来不知怎么地就不了了之了。 现在重新来看还是很容易就看懂了,不过构造十字链表还是有点困难。现在比起以前网上关于dance Linking的资料多了。遂,寻一参考之。^_^

链接如下: http://hi.baidu.com/ofeitian/blog/item/f761ef16d36f330f4b90a7ff.html

 

链表的题目本来就没写过多少,双向链表的插入都显得十分生疏,总结下:

如果要在链尾插入元素,则先更新链尾的指针,后再更新链头的指针。因为我们要靠链头指针找到原来的链尾,先更新的话就找不到了。

 

最后,感觉可以加个行指针。因为n可以达到1000左右,那样使行的删除时间大大减少。不过没时间了, 要比赛了。以后有时间再优化吧。

 

补充一下: 行最多可达到500,列最多为900。我这个程序耗时大约为360ms。

 

#include <cstdio> #define MAXW 901 #define MAXN 450901 #define INF 600 int C[MAXN+10], L[MAXN+10], R[MAXN+10], U[MAXN+10], D[MAXN+10], S[MAXW+10]; int min; void remove(const int &c) { //remove column c and all row i that A[i][c] == 1 L[R[c]] = L[c]; R[L[c]] = R[c]; //remove column c; for (int i = D[c]; i != c; i = D[i]) { //remove i that A[i][c] == 1 for (int j = R[i]; j != i; j = R[j]) { U[D[j]] = U[j]; D[U[j]] = D[j]; //decrease the count of column C[j]; --S[C[j]]; } } } void resume(const int &c) { for (int i = U[c]; i != c; i = U[i]) { for (int j = L[i]; j != i; j = L[j]) { ++S[C[j]]; U[D[j]] = j; D[U[j]] = j; } } L[R[c]] = c; R[L[c]] = c; } void dfs(const int &k) { if (R[0] == 0) { if(k < min) { min = k; } return; } int s = INF, c; for (int t = R[0]; t != 0; t = R[t]) { //select the column c which has the fewest number of element. if (S[t] < s) { s = S[t]; c = t; } } remove(c); for (int i = D[c]; i != c; i = D[i]) { for (int j = R[i]; j != i; j = R[j]) { remove(C[j]); } dfs(k + 1); for (int k = L[i]; k != i; k = L[k]) { resume(C[k]); } } resume(c); } int main(int argc, char* argv[]) { int T, i, j, k, ccnt, cnt, col, x1, x2, y1, y2, n, m, p, head, tail; scanf("%d", &T); while(T--) { min = INF; scanf("%d%d%d", &n, &m, &p); ccnt = n*m; for(i = 0; i <= ccnt; i++) { L[i] = i-1; R[i] = i+1; U[i] = D[i] = i; S[i] = 0; } L[0] = ccnt; R[ccnt] = 0; cnt = ccnt+1; for(i = 1; i <= p; i++) { head = tail = cnt; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); for(j = x1; j < x2; j++) { for(k = y1; k < y2; k++) { col = j*m+k+1; C[cnt] = col; S[col]++; //插入列中 U[cnt] = U[col]; D[U[col]] = cnt; D[cnt] = col; U[col] = cnt; //插入行中 R[tail] = cnt; L[cnt] = tail; R[cnt] = head; L[head] = cnt; tail = cnt; cnt++; } } } for(i = 1; i <= ccnt; i++) { if(!S[i]) { printf("-1/n"); break; } } if(i <= ccnt) { continue; } dfs(0); if(min != INF) { printf("%d/n", min); } else { printf("-1/n"); } } return 0; }  

你可能感兴趣的:(c,优化,360)