POJ--3074--SudokuAAA

本文探讨了数独游戏的求解算法,采用深度优先搜索策略,通过位运算优化状态存储,优先搜索可填位置较少的格子,以提高求解效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

.2738..1.
.1...6735
.......29
3.5692.8.
.........
.6.1745.3
64.......
9518...7.
.8..6534.

Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

Input

The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

Output

For each test case, print a line representing the completed Sudoku puzzle.

Sample Input
.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end
Sample Output
527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

数独问题,暴搜;
有一个优化,优先搜索可填位置少的;
同时一个位置一个位置填,一次一个位置就好;
可以用二进制储存状态;

其中我给出自己写的超时代码如下:(问题还是无法解决)TT_TT!!!

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
//考虑为bool类型也可以实现 
int row[10][10];//判断row[i][x],在i行x是否出现(bool) 
int col[10][10];//判断 col[j][y],在j列y是否出现(bool)
int map[10][10];//处理输入 
int small[10][10];//处理3*3格子(bool)
bool flag=false;
int f(int x,int y){
    return 3*((x-1)/3)+(y-1)/3+1;//返回x,y出现在哪个具体的网格 
}
void input(){
	char ch; 
	for(int i=1;i<=9;i++){
		for(int j=1;j<=9;j++){ 
			scanf("%c",&ch);
		    if(ch=='.')
		        map[i][j]=0;//处理为0元素 
		    else
				map[i][j]=ch-'0';
		    if(map[1][1]=='e'-'0'&&map[1][2]=='n'-'0'&&map[1][2]=='d'-'0'){ 
				flag=true;
				return; 
			}	 
		} 
	}
}
void init(){
    int i,j;
    memset(row,0,sizeof(row));
    memset(col,0,sizeof(col));
    memset(small,0,sizeof(small));
    for(i=1;i<=9;i++){
        for(j=1;j<=9;j++){
            if(map[i][j]){//不处理0的情况 
                int k;
                k=f(i,j);
                row[i][map[i][j]]=1;//在i行出现map[i][j];
                col[j][map[i][j]]=1;//在j列出现map[i][j]; 
                small[k][map[i][j]]=1;//map[i][j]属于第k个网格 
            }
        }
    }
}
int dfs(int x,int y){
    if(x==10)
        return 1;
    int flag=0;
    if(map[x][y]){
        if(y==9)
            flag=dfs(x+1,1);
        else
            flag=dfs(x,y+1);
        if(flag)
            return 1;
        else
            return 0;
    }
    else{
        int k=f(x,y);
        for(int i=1;i<=9;i++)
            if(!row[x][i]&&!col[y][i]&&!small[k][i]){
                map[x][y]=i;
                row[x][i]=1;
                col[y][i]=1;
                small[k][i]=1;
                if(y==9)
                    flag=dfs(x+1,1);
                else
                    flag=dfs(x,y+1);
                if(!flag){
                    map[x][y]=0;
                    row[x][i]=0;
                    col[y][i]=0;
                    small[k][i]=0;
                }
                else
                    return 1;
            }
    }
    return 0;
}
int main(){
	while(1){
		input();
		if(flag)
			break;
		else{
			init();
			getchar();//用于缓冲,不能或缺
			dfs(1,1);
			for(int i=1;i<=9;i++)
				for(int j=1;j<=9;j++)
					cout<<map[i][j];
			cout<<endl;
		}
	}
	return 0;
/***string s;
	cin>>s;
	cout<<s.size()<<endl;//输出的结果是81. 
***/
} 

AC代码如下

#include<cstdio>
#include<algorithm>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;
const int MAXN = 15;
int r[MAXN], c[MAXN], k[MAXN];
int lg[1 << 10], num[1 << 10];
char s[MAXN * MAXN], a[MAXN][MAXN];
inline int ID(int i, int j){
    return 3 * (i / 3) + j / 3;
}
inline void draw(int x, int y, int z){
    r[x] ^= 1 << z;
    c[y] ^= 1 << z;
    k[ID(x, y)] ^= 1 << z;
}
bool dfs(int cnt){
    if(cnt == 81) return true;
    int x, y, mint = 10;
    REP(i, 0, 9)
        REP(j, 0, 9)
            if(a[i][j] == '.'){
                int val = num[r[i] & c[j] & k[ID(i, j)]];
                if(!val) return false;
                if(mint > val){
                    mint = val;
                    x = i, y = j;
                }
            }      
    int tmp = r[x] & c[y] & k[ID(x, y)];
    for(; tmp; tmp -= tmp & (-tmp)){
        int t = lg[tmp & (-tmp)];
        a[x][y] = t + '1';
        draw(x, y, t);
        if(dfs(cnt + 1)) return true;
        draw(x, y, t);
        a[x][y] = '.';
    }
    return false;
}
int main(){
    REP(i, 0, 9) lg[1 << i] = i;
    REP(i, 0, 1 << 9) 
        for(int j = i; j; j -= j & (-j)) num[i]++;   
    while(scanf("%s", s) && s[0] != 'e'){
        int cnt = 0;
        REP(i, 0, 9) c[i] = r[i] = k[i] = (1 << 9) - 1;
        REP(i, 0, 9)
            REP(j, 0, 9){
                a[i][j] = s[i * 9 + j];
                if(a[i][j] != '.') cnt++, draw(i, j, a[i][j] - '1');
            }  
        dfs(cnt);
        REP(i, 0, 9)
            REP(j, 0, 9)
                s[i * 9 + j] = a[i][j];    
        puts(s);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值