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 ...
随机推荐
- 关于functools模块的wraps装饰器用途
测试环境:Python3.6.2 + win10 + Pycharm2017.3 装饰器之functools模块的wraps的用途: 首先我们先写一个装饰器 # 探索functools模块wraps ...
- log4j2配置推荐
<?xml version="1.0" encoding="UTF-8"?> <!-- monitorInterval为监听配置变化的间隔,3 ...
- 【题解】Luogu P5072 [Ynoi2015]盼君勿忘
众所周知lxl是个毒瘤,Ynoi道道都是神仙题,题面好评 原题传送门 一看这题没有修改操作就知道这是莫队题 我博客里对莫队的简单介绍 既然是莫队,我们就要考虑每多一个数或少一个数对答案的贡献是什么 假 ...
- linux command wrap
$ cat tmux-attach ] ; then tmux ls else tmux attach -t $ fi $ cat /usr/bin/cscope-go.sh #!/bin/bash ...
- JavaScript中this的用法 及 如何改变this的指向
要懂得JavaScript中this的用法,首先需要知道,JavaScript中的作用域相关知识. var fun = function(){ var flag = 1; console.log(fl ...
- QML中打印
1.console.log("123"); 2.console.log("a is ", a, "b is ", b); 3.打印代码块时间 ...
- 复旦大学2016--2017学年第二学期高等代数II期末考试情况分析
一.期末考试成绩班级前十五名 林晨(93).朱民哲(92).何陶然(91).徐钰伦(91).吴嘉诚(91).于鸿宝(91).宁盛臻(90).杨锦文(89).占文韬(88).章俊鑫(87).颜匡萱(87 ...
- centOS6.8开放防火墙端口
1.找到防火墙配置文件,/etc/sysconfig/iptables.如果是新装的linux系统,防火墙默认是被禁掉的,没有配置任何防火墙策略,所以不存在iptables.需要在控制台使用iptab ...
- 设置Eclipse具有字母自动联想
Window->Preferences->Java->Editor->ContentAssist(内容助手)里面的Enable auto activation里面第二行再加上a ...
- Python3 tkinter基础 Button bg 按钮的背景颜色
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...