回溯算法 -- 数独问题

还是蓝桥杯上遇到的题,仿佛蓝桥杯成了初恋一般又爱又恨。。。


数独问题


你一定听说过“数独”游戏。
如图,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。

数独的答案都是唯一的,所以,多个解也称为无解。

本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。

本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。

格式要求,输入9行,每行9个字符,0代表未知,其它数字为已知。
输出9行,每行9个数字表示数独的解。



思路:依然是暴力+回溯,依次判断每一行每一列从0-9可以放入的数,然后递归。

0-9抖不满足条件时,回溯到上一个。

代码:

package lanqiaobei;
import java.io.*;
import java.util.Scanner;
public class shudu {
public int a[][] = new int[9][9];
public boolean is_row_col_repeat(int row,int col,int n){
	for(int i=0;i<9;i++){
		if(a[row][i] == n)
			return false;
	}
	for(int i=0;i<9;i++){
		if(a[i][col] == n)
			return false;
	}
	return true;
}
public int get_row_range(int row){//判断同色的格子时,判断为哪个大格子
	if(0<=row && row<=2)
		return 0;
	else if(3<=row && row<=5)
		return 3;
	else return 6;
}
public int get_col_range(int col){//判断同色的格子时,判断为哪个大格子
	if(0<=col && col<=2)
		return 0;
	else if(3<=col && col<=5)
		return 3;
	else return 6;
}
public boolean is_block_repeat(int x,int y,int n){
	for(int i=x;i<=x+2;i++)
		for(int j=y;j<=y+2;j++){
			{
				if(a[i][j] == n)
					return false;
			}
		}
	return true;
}
public void dfs(int row,int col){
	if(row >= 9)
	{
		for(int i=0;i<=8;i++){
			for(int j=0;j<=8;j++){
				System.out.print(a[i][j]);
			}
		System.out.println("");
		}
	}
	int x = get_row_range(row);
	int y = get_col_range(col);
	if(a[row][col] == 0){
	for(int i=1;i<=9;i++){//数字1-9
		if( is_row_col_repeat(row,col,i) && is_block_repeat(x,y,i)){
			a[row][col] = i;
			dfs(row + (col + 1) / 9, (col + 1) % 9);
		}
	}
	//如果1-9都不行
	a[row][col] = 0;
	return;
	}else {
		dfs(row + (col + 1) / 9, (col + 1) % 9);
	}
}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		shudu s = new shudu();
		Scanner scanner = new Scanner(System.in);
		String str;
		char[] ai;
		for(int i = 0; i < 9; i++) {
			str = scanner.nextLine();
			ai = str.toCharArray();
			for(int j = 0; j < 9; j++) {
				s.a[i][j] = Integer.parseInt(ai[j] + "");
			}
		}
		s.dfs(0, 0);
		}	
	/*
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700
	 */

}

输入

005300000

800000020

070010500

400005300

010070006

003200080

060500009

004000030

000009700


输出答案:

145327698

839654127

672918543

496185372

218473956

753296481

367542819

984761235

521839764


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值