hust1017 Dancing Links

这题因为建图卡了好久,Dancing Links的入门题,不想多说什么。想了解的请参看Knuth的论文。

这里学会了一个很方便的双向链表插入算法,如果要将x插入到双向链表中,只要先更新x的指针域,然后调用dlx的第二步就可以了。

在init函数有所实现。

 

我的代码:

#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define DEBUG using namespace std; const int nColumn = 1100; const int nRow = 1100; const int nNode = nRow*nColumn; const int head = 0; const int oo = 0x3f3f3f3f; int right[nNode], left[nNode], up[nNode], down[nNode]; int cnt[nColumn]; int result[nNode], nResult; int row[nRow][nColumn], column[nColumn][nRow]; int cntRow[nRow], cntColumn[nColumn]; int nR, nC; int getColumn(int id) { if (id % nC) return id % nC; else return nC; } int getId(int r, int c) { return r * nC + c; } int getRow(int id) { return (id - 1) / nC; } void remove(const int& x) { left[right[x]] = left[x]; right[left[x]] = right[x]; for (int r = down[x]; r != x; r = down[r]) { for (int c = right[r]; c != r; c = right[c]) { up[down[c]] = up[c]; down[up[c]] = down[c]; cnt[getColumn(c)]--; } } } void resume(const int& x) { for (int r = up[x]; r != x; r = up[r]) { for (int c = left[r]; c != r; c = left[c]) { cnt[getColumn(c)]++; up[down[c]] = c; down[up[c]] = c; } } left[right[x]] = x; right[left[x]] = x; } bool dfs(const int& k) { if (right[head] == head) { nResult = k; return true; } int S = oo, x = 0; for (int t = right[head]; t != head; t = right[t]) { if (cnt[t] < S) { S = cnt[t]; x = t; } } remove(x); for (int r = down[x]; r != x; r = down[r]) { result[k] = getRow(r); for (int c = right[r]; c != r; c = right[c]) { remove(getColumn(c)); } if (dfs(k + 1)) return true; for (int c = left[r]; c != r; c = left[c]) { resume(getColumn(c)); } } resume(x); return false; } bool init(int r, int c) { int id, pre; //deal with list heads left[head] = c; right[head] = 1; for (int i = 1; i <= c; i++) { left[i] = i - 1; right[i] = (i + 1) % (c + 1); up[i] = down[i] = i; cnt[i] = cntColumn[i]; if (cnt[i] == 0) return false; } //deal with columns for (int i = 1; i <= c; i++) { for (int j = 0; j < cnt[i]; j++) { id = getId(column[i][j], i); up[id] = i; down[id] = down[i]; up[down[id]] = id; down[up[id]] = id; left[id] = right[id] = id; } } //deal with rows for (int i = 1; i <= r; i++) { for (int j = 1; j < cntRow[i]; j++) { id = getId(i, row[i][j]); pre = getId(i, row[i][j - 1]); left[id] = pre; right[id] = right[pre]; left[right[id]] = id; right[left[id]] = id; } } return true; } int main() { int x; #ifdef DEBUG1 freopen("in.txt", "r", stdin); #endif while (~scanf("%d%d", &nR, &nC)) { for (int i = 1; i <= nC; i++) { cntColumn[i] = 0; } for (int i = 1; i <= nR; i++) { scanf("%d", &cntRow[i]); for (int j = 0; j < cntRow[i]; j++) { scanf("%d", &x); row[i][j] = x; column[x][cntColumn[x]++] = i; } } if (!init(nR, nC)) { puts("NO"); continue; } if (!dfs(0)) { puts("NO"); continue; } printf("%d", nResult); for (int i = 0; i < nResult; i++) { printf(" %d", result[i]); } puts(""); } return 0; }

 

 

你可能感兴趣的:(c,算法,list,OO,UP)