POJ 3076 Sudoku
思路:
dfs + 剪枝
首先,如果这个位置只能填一种字母,那就直接填
其次,如果对于每一种字母,如果某一列或者某一行或者某一块只能填它,那就填它
然后,对于某个位置如果不能填字母了,或者某种字母在一行一列或一块中出向了两次以上,说明当前方案不成立
最后贪心地从可选情况少的往下搜
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head const int N = ;
int mp[N][N];
int st[N][N];
int sum = ;
char s[N][N+];
void add(int x, int y, int t) {
mp[x][y] = t;
sum++;
for (int i = ; i <= ; i++) {
st[i][y] |= <<t-;
st[x][i] |= <<t-;
}
int xx = (x+)/, yy = (y+)/;
for (int i = (xx-)* + ; i <= xx*; i++) {
for (int j = (yy-)* + ; j <= yy*; j++) {
st[i][j] |= <<t-;
}
}
}
void print() {
for (int i = ; i <= ; i++) {
for (int j = ; j <= ; j++) {
putchar(mp[i][j]-+'A');
}
puts("");
}
puts("");
}
bool dfs() {
if(sum == ) {
print();
return true;
} for (int i = ; i <= ; i++) {
for (int j = ; j <= ; j++) {
if(!mp[i][j]) {
int cnt = , t = ;
for (int k = ; k <= ; k++) {
if((st[i][j] & (<<k-)) == ) {
cnt++;
t = k;
if(cnt == ) break;
}
}
if(!cnt) return false;
if(cnt == ) add(i, j, t);
}
}
} for (int i = ; i <= ; i++) {
for (int k = ; k <= ; k++) {
int cnt1 = , cnt2 = , y;
for (int j = ; j <= ; j++) {
if(mp[i][j] == k) cnt1++;
if(cnt1 == ) return false;
if(!mp[i][j] && (st[i][j] & (<<k-)) == ) cnt2++, y = j;
}
if(!cnt1 && !cnt2) return false;
if(!cnt1 && cnt2 == ) add(i, y, k);
}
} for (int j = ; j <= ; j++) {
for (int k = ; k <= ; k++) {
int cnt1 = , cnt2 = , x;
for (int i = ; i <= ; i++) {
if(mp[i][j] == k) cnt1++;
if(cnt1 == ) return false;
if(!mp[i][j] && (st[i][j] & (<<k-)) == ) cnt2++, x = i;
}
if(!cnt1 && !cnt2) return false;
if(!cnt1 && cnt2 == ) add(x, j, k);
}
} for (int i = ; i <= ; i++) {
int x = (i+)/, y = i - (x-)*;
for (int k = ; k <= ; k++) {
int cnt1 = , cnt2 = , xx, yy;
for (int ii = (x-)*+; ii <= x*; ii++) {
for (int jj = (y-)*+; jj <= y*; jj++) {
if(mp[ii][jj] == k) cnt1++;
if(cnt1 == ) return false;
if(!mp[ii][jj] && (st[ii][jj] & (<<k-)) == ) cnt2++, xx = ii, yy = jj;
}
}
if(!cnt1 && !cnt2) return false;
if(!cnt1 && cnt2 == ) add(xx, yy, k);
}
}
if(sum == ) {
print();
return true;
} int mn = N, x, y;
for (int i = ; i <= ; i++) {
for (int j = ; j <= ; j++) {
if(!mp[i][j]) {
int cnt = ;
for (int k = ; k <= ; k++) {
if((st[i][j] & (<<k-)) == ) {
cnt++;
if(cnt >= mn) break;
}
}
if(cnt < mn) {
mn = cnt;
x = i;
y = j;
}
}
}
}
int tst[N][N], tmp[N][N];
memcpy(tst, st, sizeof(st));
memcpy(tmp, mp, sizeof(mp));
int tsum = sum; for (int k = ; k <= ; k++) {
if((st[x][y] & (<<k-)) == ) {
add(x, y, k);
bool f = dfs();
if(!f) {
memcpy(st, tst, sizeof(tst));
memcpy(mp, tmp, sizeof(tmp));
sum = tsum;
}
else return true;
}
}
return false;
}
int main() {
while(scanf("%s", s[]+) != EOF){
for (int i = ; i <= ; i++) {
scanf("%s", s[i]+);
}
sum = ;
mem(mp, );
mem(st, );
for (int i = ; i <= ; i++) {
for (int j = ; j <= ; j++) {
if(isalpha(s[i][j])) add(i, j, s[i][j] - 'A' + );
}
}
dfs();
}
return ;
}
/*
--A----C-----O-I
-J--A-B-P-CGF-H-
--D--F-I-E----P-
-G-EL-H----M-J--
----E----C--G---
-I--K-GA-B---E-J
D-GP--J-F----A--
-E---C-B--DP--O-
E--F-M--D--L-K-A
-C--------O-I-L-
H-P-C--F-A--B---
---G-OD---J----H
K---J----H-A-P-L
--B--P--E--K--A-
-H--B--K--FI-C--
--F---C--D--H-N-
*/
POJ 3076 Sudoku的更多相关文章
- (简单) POJ 3076 Sudoku , DLX+精确覆盖。
Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells ...
- POJ 3076 Sudoku DLX精确覆盖
DLX精确覆盖模具称号..... Sudoku Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 4416 Accepte ...
- POJ 3076 Sudoku (dancing links)
题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是依照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- ...
- 搜索(DLX): POJ 3074 3076 Sudoku
POJ 3074 : Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller ...
- 深搜+回溯 POJ 2676 Sudoku
POJ 2676 Sudoku Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17627 Accepted: 8538 ...
- POJ 3076 / ZOJ 3122 Sudoku(DLX)
Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells ...
- 【POJ 3076】 Sudoku
[题目链接] http://poj.org/problem?id=3076 [算法] 将数独问题转化为精确覆盖问题,用Dancing Links求解 [代码] #include <algorit ...
- 【POJ】3076 Sudoku
DLX第一题,模板留念. /* 3076 */ #include <iostream> #include <string> #include <map> #incl ...
- Sudoku POJ - 3076
Sudoku Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 5769 Accepted: 2684 Descripti ...
随机推荐
- 【题解】Luogu SP3267 DQUERY - D-query
原题传送门 这题和Luogu P1972 [SDOI2009]HH的项链很像,只是数据大小有些差别,题解 我博客里对莫队的介绍 我们在排序询问时,普通是这样qaq inline bool cmp(re ...
- 神秘的.user.ini文件
原文链接:https://segmentfault.com/a/1190000011552335
- Codeforces 841D Leha and another game about graph - 差分
Leha plays a computer game, where is on each level is given a connected graph with n vertices and m ...
- Io流的使用
file的使用 文件流的使用 FileInpunStream FileOutOputStream ----------字符流 FileReader Filewriter --------字节流 ...
- topcoder srm 663 div1
problem1 link 每次枚举$S$的两种变化,并判断新的串是否是$T$的子串.不是的话停止搜索. problem2 link 首先考慮增加1个面值为1的硬币后,$ways$数组有什么变化.设原 ...
- Window 对象 HTML框架标签(Frame)
Window 对象 Window 对象表示浏览器中打开的窗口. 如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外 ...
- Python3 tkinter基础 Frame event.x 输出鼠标左右键点击的位置
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Ubuntu: repository/PPA 源
在Ubuntu中,每个PPA源是单独存放在/etc/apt/sources.list.d/文件夹中的,进入到该文件夹,使用ls命令查询即可列出当前系统添加的PPA源. 添加 sudo add-apt- ...
- 永久修改VS include目录
原文:https://blog.csdn.net/sysprogram/article/details/49214727 VS2008在选项里可以设置全局的Include目录和Lib目录, 但是VS2 ...
- newcoder F石头剪刀布(DFS + 思维)题解
题意:wzms 今年举办了一场剪刀石头布大赛,bleaves 被选为负责人. 比赛共有 2n 个人参加, 分为 n 轮, 在每轮中,第 1 位选手和第 2 位选手对战,胜者作为新的第 1 位选手, 第 ...