poj 2676
题意:数独
思路:
1.dancing link
2. dfs(填写每一个九宫格) 加剪枝 回溯
- 排除已出现的数字( sqr line column)
- 收缩顺序 优先选取已知数字较多的方块搜索
#include <iostream>
#include<cstring>
#include <cstdio>
#define mem(a) memset(a,0,sizeof(a))
#define MAXNUM 9
using namespace std;
int sudoku[MAXNUM][MAXNUM];
int line[MAXNUM][MAXNUM+1],column[MAXNUM][MAXNUM+1];
int sqr[3][3][1+MAXNUM];
int cntsqr[3][3];
int esqr[3][3][2] = {{{3,3},{3,6},{3,9}},{{6,3},{6,6},{6,9}},{{9,3},{9,6},{9,9}}};
int cnt;
int maxX,maxY;
void init(){
cnt = 0;
mem(sudoku);
mem(line);
mem(column);
mem(sqr);
mem(cntsqr);
}
void picksqr(){
maxX = maxY = -1;
for (int i = 0;i<3;i++){
for (int j = 0;j<3;j++){
if (cntsqr[i][j] != MAXNUM){
if (maxX == -1) {
maxX = i,maxY = j;
} else {
if (cntsqr[i][j] > cntsqr[maxX][maxY])
maxX = i,maxY = j;
}
}
}
}
}
void turn_back(int i,int j,int k){
sudoku[i][j] = 0;
line[i][k] = column[j][k] = 0;
sqr[i/3][j/3][k] = 0;
cntsqr[i/3][j/3]--;
}
void update(int i,int j,int k){
sudoku[i][j] = k;
line[i][k] = column[j][k] = 1;
sqr[i/3][j/3][k] = 1;
cntsqr[i/3][j/3]++;
}
bool dfs_sqr(int Sline,int Scolumn){
int maxl = esqr[Sline/3][Scolumn/3][0],maxc = esqr[Sline/3][Scolumn/3][1];
bool placed = false;
for (int i = Sline;i<maxl && !placed;i++){
for (int j = Scolumn;j<maxc && !placed;j++){
if (sudoku[i][j] == 0){
placed = true;
for (int k = 1;k<=MAXNUM;k++){
if (!sqr[i/3][j/3][k] && !line[i][k] && !column[j][k]){
update(i,j,k);
if(cntsqr[i/3][j/3] == MAXNUM){
cnt++;
if (cnt == 9) return true;
picksqr();
if (dfs_sqr(maxX*3,maxY*3)) return true;
cnt--;
}else {
if (dfs_sqr(i,Scolumn)) return true;
}
turn_back(i,j,k);
}
}
}
}
}
return false;
}
int main()
{
int test;
scanf("%d",&test);
while(test--){
init();
for (int i = 0;i<9;i++){
char str[16];
scanf("%s",str);
for (int j = 0;j<9;j++){
int num = str[j] - '0';
if (num != 0) {
update(i,j,num);
}
if ((i == 2 || i == 5 || i == 8 ) && (j == 2 || j == 5 || j == 8 )){
if (cntsqr[i/3][j/3] == MAXNUM)
cnt++;
}
}
}
picksqr();
dfs_sqr(maxX*3,maxY*3);
for (int i = 0;i<MAXNUM;i++){
for(int j = 0;j<MAXNUM;j++)
printf("%d",sudoku[i][j]);
printf("\n");
}
}
return 0;
}
poj 2918
略微修改上述代码可过
poj3074
上诉思路不可过
参考poj 3074 可过
poj 3076
上述思路均不可过
似乎需要使用dancing link