HDU 3909 Sudoku(数独转DLX精确覆盖)
来源:互联网 发布:java软件设计什么 编辑:程序博客网 时间:2024/05/17 23:36
题目地址
题意:给你一个n,然后给你一个n^2阶的数独,n分别有2,3,4这3种情况,然后你判断这个数独是不是有唯一的一个解,如果没有解的话输出”No Solution”,多个解的话就是输出”Multiple Solutions”,否则判断这个唯一解是不是最小解(最小解就是把任何一个给定的数变为不确定的话就会有多组解)
思路:我们通过map去映射字符与数字的关系,然后我们在DLX中加一个变量记录有多少种情况,(剪枝:当大于等于2的时候说明一定是有多组解的所以我们在tot等于2的时候直接让他返回就好了,因为已经是多组解了,没有必要继续搜索下去),如果我们只有一组解的话,我们就枚举每一个不为’.’的点,把他置为’.’,再进行一边DLX判断他是不是有多组解,如果有一个没有的就是输出”Not Minimal” ,否则输出数独结果就好了。
PS:这题还是蛮考对数独转DLX精确覆盖的理解的,题目其实不难,只是需要细心。我就是忘记把我测试输出的东西删掉了导致找了一天的bug。
#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <cmath>#include <cstdio>#include <algorithm>#include <iomanip>#define N 110#define MAXSIZE 1010*1010#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1 using namespace std;const LL mod = 1000000007;struct node { int left, right, up, down, col, row;}mapp[MAXSIZE];int S[MAXSIZE], H[MAXSIZE];//S记录该列中1元素的个数int head, cnt;int ans[MAXSIZE];int len;int tot;struct Dancing_Links_X { void init(int m) { head = 0; tot = 0; for (int i = 0; i <= m; i++) { S[i] = 0; mapp[i].up = mapp[i].down = i; mapp[i].left = (i == 0 ? m : i - 1); mapp[i].right = (i == m ? 0 : i + 1); } cnt = m; memset(H, -1, sizeof(H)); } void link(int x, int y) { cnt++; mapp[cnt].row = x; mapp[cnt].col = y; S[y]++; mapp[cnt].up = mapp[y].up; mapp[cnt].down = y; mapp[mapp[y].up].down = cnt; mapp[y].up = cnt; if (H[x] == -1) H[x] = mapp[cnt].left = mapp[cnt].right = cnt; else { mapp[cnt].left = mapp[H[x]].left; mapp[cnt].right = H[x]; mapp[mapp[H[x]].left].right = cnt; mapp[H[x]].left = cnt; } } void remove(int c) {//删去c这个点,以及关联的一列 mapp[mapp[c].right].left = mapp[c].left; mapp[mapp[c].left].right = mapp[c].right; for (int i = mapp[c].down; i != c; i = mapp[i].down) { for (int j = mapp[i].right; j != i; j = mapp[j].right) { mapp[mapp[j].down].up = mapp[j].up; mapp[mapp[j].up].down = mapp[j].down; --S[mapp[j].col]; } } } void resume(int c) {//恢复c这个点,以及关联的一列 for (int i = mapp[c].up; i != c; i = mapp[i].up) { for (int j = mapp[i].left; j != i; j = mapp[j].left) { ++S[mapp[j].col]; mapp[mapp[j].down].up = mapp[mapp[j].up].down = j; } } mapp[mapp[c].right].left = mapp[mapp[c].left].right = c; } void dance1(int k) { if (mapp[head].right == head) { len = k; tot++; return; } int s = inf, c; for (int t = mapp[head].right; t != head; t = mapp[t].right) { if (S[t] < s) s = S[t], c = t; } remove(c); for (int i = mapp[c].down; i != c; i = mapp[i].down) { ans[k] = mapp[i].row; for (int j = mapp[i].right; j != i; j = mapp[j].right) { remove(mapp[j].col); } dance1(k + 1); if (tot == 2) { return; } for (int j = mapp[i].left; j != i; j = mapp[j].left) { resume(mapp[j].col); } } resume(c); } bool dance(int k) { if (mapp[head].right == head) { len = k; //cout << endl << len << endl << endl; return true; } int s = inf, c; for (int t = mapp[head].right; t != head; t = mapp[t].right) { if (S[t] < s) s = S[t], c = t; } remove(c); for (int i = mapp[c].down; i != c; i = mapp[i].down) { ans[k] = mapp[i].row; for (int j = mapp[i].right; j != i; j = mapp[j].right) { remove(mapp[j].col); } if (dance(k + 1)) { return true; } for (int j = mapp[i].left; j != i; j = mapp[j].left) { resume(mapp[j].col); } } resume(c); return false; }}DLX;char mat[N][N];map<char, int>map1;map<int, char>map2;void build(int n, int m) { DLX.init(m * m * 4); for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { if (mat[i][j] != '.') { int r = (i * m + j) * m + map1[mat[i][j]]; int c1 = i * m + j + 1; int c2 = m * m + i * m + map1[mat[i][j]]; int c3 = 2 * m * m + j * m + map1[mat[i][j]]; int c4 = 3 * m * m + (i / n * n + j / n) * m + map1[mat[i][j]]; DLX.link(r, c1); DLX.link(r, c2); DLX.link(r, c3); DLX.link(r, c4); S[c1] = S[c2] = S[c3] = S[c4] = -1; } } } for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { if (mat[i][j] == '.') { for (int k = 1; k <= m; k++) { int r = (i * m + j) * m + k; int c1 = i * m + j + 1; int c2 = m * m + i * m + k; int c3 = 2 * m * m + j * m + k; int c4 = 3 * m * m + (i / n * n + j / n) * m + k; if (~S[c1] && ~S[c2] && ~S[c3] && ~S[c4]) { DLX.link(r, c1); DLX.link(r, c2); DLX.link(r, c3); DLX.link(r, c4); } } } } }}int main() { cin.sync_with_stdio(false); int n, m; map1.clear(); map1['1'] = 1;map1['2'] = 2;map1['3'] = 3;map1['4'] = 4; map1['5'] = 5;map1['6'] = 6;map1['7'] = 7;map1['8'] = 8; map1['9'] = 9;map1['A'] = 10;map1['B'] = 11;map1['C'] = 12; map1['D'] = 13;map1['E'] = 14;map1['F'] = 15;map1['G'] = 16; map2.clear(); map2[1] = '1';map2[2] = '2';map2[3] = '3';map2[4] = '4'; map2[5] = '5';map2[6] = '6';map2[7] = '7';map2[8] = '8'; map2[9] = '9';map2[10] = 'A';map2[11] = 'B';map2[12] = 'C'; map2[13] = 'D';map2[14] = 'E';map2[15] = 'F';map2[16] = 'G'; while (cin >> n) { m = n*n; for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { cin >> mat[i][j]; } } build(n, m); len = inf; DLX.dance1(0); if (tot == 0) { cout << "No Solution" << endl; } else if (tot == 1) { bool flag = true; for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { if (mat[i][j] == '.') continue; char ch = mat[i][j]; mat[i][j] = '.'; build(n, m); len = inf; DLX.dance1(0); if (tot != 2) { flag = false; break; } mat[i][j] = ch; } } if (!flag) { cout << "Not Minimal" << endl; } else { build(n, m); len = inf; DLX.dance(0); for (int i = 0; i < len; i++) { int Orz = (ans[i] - 1) % m + 1; int x = (ans[i] - 1) / m / m; int y = (ans[i] - 1) / m % m; if (mat[x][y] != '.') continue; mat[x][y] = map2[Orz]; } for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { cout << mat[i][j]; } cout << endl; } } } else { cout << "Multiple Solutions" << endl; } } return 0;}
阅读全文
0 0
- HDU 3909 Sudoku(数独转DLX精确覆盖)
- HDU 4069 Squiggly Sudoku DLX 精确覆盖
- POJ 3074 Sudoku(DLX+精确覆盖)
- DLX精确覆盖 poj2676 Sudoku
- HDU 2780 Su-Su-Sudoku(数独用DLX精确覆盖求解)
- poj 3074 Sudoku (精确覆盖,DLX,搜索)
- DLX(精确覆盖) POJ 3074 Sudoku
- POJ 3074 Sudoku DLX精确覆盖
- POJ 3076 Sudoku DLX精确覆盖
- DLX精确覆盖 hdu4069 Squiggly Sudoku
- POJ 3076 Sudoku 精确覆盖问题DLX
- DLX(精确覆盖) HDU 3663 Power Stations
- DLX(精确覆盖) 16*16数独 POJ 3076 Sudoku
- LA 2659 && poj 3076 && zoj 3122 Sudoku(精确覆盖 + DLX)
- POJ 3074 Sudoku 转化精确覆盖问题DLX
- [DLX精确覆盖] hdu 3663 Power Stations
- HDU 3663 Power Stations DLX精确覆盖
- poj 3740 DLX(精确覆盖)
- java中的转发,重定向
- 大数计算 总结
- Java面试题集(51-70)
- 相似类型对比
- HDU 5661 Claris and XOR(贪心)
- HDU 3909 Sudoku(数独转DLX精确覆盖)
- Pandas数据排序
- leetcode 695. Max Area of Island 解法
- 学习日志————国庆总结
- 0-1背包问题-回溯&贪心算法-C#Demo
- 51NOD-1011 最大公约数GCD
- 数据结构:实验二线性表综合实验②单链表
- html知识
- 每天一篇博客,绝不断更,以此激励自己