POJ 3076 Sudoku 精确覆盖问题DLX
2017-08-14 10:51
417 查看
题目:
http://poj.org/problem?id=3076题意:
16宫格,用大写字母A~P填充,输出一种方案思路
跳舞链。注意建列约束的时候,按照存在性、行、列、块的顺序比行、列、块、存在性的顺序建约束快了差不多10倍,很迷。。。#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int X = 300000 + 10, N = 5000 + 10, M = 1200 + 10, INF = 0x3f3f3f3f; struct DLX { int U[X], D[X], L[X], R[X], row[X], col[X]; int H , S[M]; int head, sz, tot, n, m, ans ; void init(int _n, int _m) { n = _n, m = _m; for(int i = 0; i <= m; i++) L[i] = i-1, R[i] = i+1, U[i] = D[i] = i, S[i] = 0; head = 0, tot = 0, sz = m; L[head] = m, R[m] = head; for(int i = 1; i <= n; i++) H[i] = -1; } void link(int r, int c) { ++S[col[++sz]=c]; row[sz] = r; D[sz] = D[c], U[D[c]] = sz; U[sz] = c, D[c] = sz; if(H[r] < 0) H[r] = L[sz] = R[sz] = sz; else R[sz] = R[H[r]], L[R[H[r]]] = sz, L[sz] = H[r], R[H[r]] = sz; } void del(int c) { L[R[c]] = L[c], R[L[c]] = R[c]; for(int i = D[c]; i != c; i = D[i]) for(int j = R[i]; j != i; j = R[j]) D[U[j]] = D[j], U[D[j]] = U[j], --S[col[j]]; } void recover(int c) { for(int i = U[c]; i != c; i = U[i]) for(int j = L[i]; j != i; j = L[j]) D[U[j]] = U[D[j]] = j, ++S[col[j]]; R[L[c]] = L[R[c]] = c; } bool dance(int dep) { if(R[head] == head) { tot = dep-1; return true; } int c = R[head]; for(int i = R[head]; i != head; i = R[i]) if(S[i] < S[c]) c = i; del(c); for(int i = D[c]; i != c; i = D[i]) { ans[dep] = row[i]; for(int j = R[i]; j != i; j = R[j]) del(col[j]); if(dance(dep + 1)) return true; for(int j = L[i]; j != i; j = L[j]) recover(col[j]); } recover(c); return false; } }dlx; int encode(int a, int b, int c, int len) { return a*len*len + b*len + c; } void calc(int x, int y, int k, int len) { int r = ((x-1) * len + (y-1)) * len + k; dlx.link(r, encode(0, x-1, y, len)); dlx.link(r, encode(1, x-1, k, len)); dlx.link(r, encode(2, y-1, k, len)); int base = 4; int block = (x-1) / base * base + (y-1) / base + 1; dlx.link(r, encode(3, block-1, k, len)); // dlx.link(r, (x-1) * len + y); // dlx.link(r, len*len + (x-1) * len + k); // dlx.link(r, len*len*2 + (y-1) * len + k); // // int base = 4; // int block = (x-1) / base * base + (y-1) / base + 1; // dlx.link(r, len*len*3 + (block-1) * len + k); } //有两个不同的输出函数,用哪一个都可以,之前用的注释掉的这个,这次用另外一个 //void print(int len) //{ // sort(dlx.ans + 1, dlx.ans + 1 + dlx.tot); // for(int i = 1; i <= len; i++) // { // for(int j = 1; j <= len; j++) // printf("%c", dlx.ans[(i-1)*len+j] - ((i-1)*len + (j-1)) * len - 1 + 'A'); // printf("\n"); // } //} void recode(int val, int &a, int &b, int &c) { val--; c = val % 16; val /= 16; b = val % 16; val /= 16; a = val; } void print(int len, char str[][20]) { int x, y, k; for(int i = 1; i <= dlx.tot; i++) { recode(dlx.ans[i], x, y, k); str[x+1][y+1] = 'A' + k; } for(int i = 1; i <= len; i++) printf("%s\n", str[i] + 1); } int main() { int len = 16, cas = 0; char str[20][20]; while(~ scanf("%s", str[1]+1)) { for(int i = 2; i <= len; i++) scanf("%s", str[i]+1); if(cas++ != 0) printf("\n"); dlx.init(len * len * len, len * len * 4); for(int i = 1; i <= len; i++) for(int j = 1; j <= len; j++) if(str[i][j] == '-') for(int k = 1; k <= len; k++) calc(i, j, k, len); else calc(i, j, str[i][j]-'A'+1, len); dlx.dance(1); //print(len); print(len, str); } return 0; }
相关文章推荐
- LA 2659 && poj 3076 && zoj 3122 Sudoku(精确覆盖 + DLX)
- DLX(精确覆盖) 16*16数独 POJ 3076 Sudoku
- POJ 3076 Sudoku DLX精确覆盖
- (简单) POJ 3076 Sudoku , DLX+精确覆盖。
- POJ 3074 Sudoku 转化精确覆盖问题DLX
- POJ 3076 Sudoku DLX精确覆盖
- POJ 3074 Sudoku(DLX+精确覆盖)
- LA_2659_POJ_3076_ZOJ_3122_Sudoku(DancingLinksX精确覆盖,数独题模板)
- (简单) POJ 3074 Sudoku, DLX+精确覆盖。
- poj3074 Sudoku 转化为精确覆盖问题 DLX
- POJ 3074 Sudoku DLX精确覆盖
- POJ 3074 DLX精确覆盖求解数独问题
- POJ_3740——精确覆盖问题,DLX模版
- DLX(精确覆盖) POJ 3074 Sudoku
- poj 3074 Sudoku (精确覆盖,DLX,搜索)
- poj 3076 Sudoku 数独(16*16)+精确覆盖+DLX 只输出一组解
- POJ 3074 Sudoku DLX精确覆盖
- POJ_3074_Sudoku(DancingLinksX精确覆盖)
- ZOJ 3209 Treasure Map (DLX精确覆盖问题)
- DLX精确覆盖 poj2676 Sudoku