POJ_2676:数独问题-DFS暴力搜索

本文介绍了一种解决数独问题的算法实现,通过深度优先搜索(DFS)的方法找到合法的填充方案。文章提供了一个完整的Java程序示例,演示了如何验证每一步填充是否符合数独规则,并最终输出解决方案。

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


                                                                                                                          Sudoku
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 19230 Accepted: 9241 Special Judge

Description

Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the cells are written decimal digits from 1 to 9. The other cells are empty. The goal is to fill the empty cells with decimal digits from 1 to 9, one digit per cell, in such way that in each row, in each column and in each marked 3x3 subsquare, all the digits from 1 to 9 to appear. Write a program to solve a given Sudoku-task.

Input

The input data will start with the number of the test cases. For each test case, 9 lines follow, corresponding to the rows of the table. On each line a string of exactly 9 decimal digits is given, corresponding to the cells in this line. If a cell is empty it is represented by 0.

Output

For each test case your program should print the solution in the same format as the input data. The empty cells have to be filled according to the rules. If solutions is not unique, then the program may print any one of them.

Sample Input

1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107

Sample Output

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127
数独问题;注意DFS在回溯时要进行还原,注意标志位的运用(只要求输出一个结果),迭代从0到80比较慢,从80到0较快
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Test39_poj2676 {
	static int[][] Maze = new int[9][9];
	static int flsg = 0;// 标志位

	public static void main(String[] args) throws FileNotFoundException {
		Scanner in = new Scanner(new FileInputStream(
				"E:\\Test_Case\\Test39_poj2676.txt"));
		// Scanner in = new Scanner(System.in);
		int caseNum = in.nextInt();
		for (int i = 0; i < caseNum; i++) {
			for (int j = 0; j < 9; j++) {
				String rowNum = in.next();
				for (int m = 0; m < rowNum.length(); m++) {
					Maze[j][m] = Integer.parseInt(rowNum.substring(m, m + 1));
				}
			}
			flsg = 0;// 初始化标志位的值
			// 开始迭代,倒着迭代
			DFS(80);
		}
	}

	// 迭代体
	public static void DFS(int step) {
		int row = step / 9;// 点的横坐标
		int column = step % 9;// 点的纵坐标
		// 结束条件
		if (step == -1) {
			flsg = 1;// 将标志位置1
			// 输出结果
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++) {
					System.out.print(Maze[i][j]);
				}
				System.out.println();
			}
			return;
		}
		if (Maze[row][column] == 0) {// 如果这个位置的值为0
			for (int temp = 1; temp < 10; temp++) {// 从1到9进行遍历
				// 判定行、列、分区是否有重复
				if (isSafe(row, column, temp)) {
					Maze[row][column] = temp;// 赋值
					DFS(step - 1);// 继续下一次迭代
					Maze[row][column] = 0;// 这个地方要进行还原!
					// 只要求输出一个结果,所以当标志位为1(已经输出一次)时,直接退出
					if (flsg == 1) {
						return;
					}
				}
			}
		} else {// 如果这个位置的值不为0,继续下个位置
			DFS(step - 1);
		}
	}

	// 判断在行、列、分区是否有重复
	public static boolean isSafe(int row, int column, int temp) {
		boolean isF = true;
		for (int i = 0; i < 9; i++) {
			// 1.行不能有重复
			if (Maze[row][i] == temp) {
				isF = false;
				return isF;
			}
			// 2.列不能有重复
			if (Maze[i][column] == temp) {
				isF = false;
				return isF;
			}
		}
		// 3.确定分区,分区内也不能有重复
		int[] tempX = partition(row);
		int[] tempY = partition(column);
		// 遍历此点所在的分区
		for (int i = tempX[0]; i <= tempX[1]; i++) {
			for (int j = tempY[0]; j <= tempY[1]; j++) {
				if (Maze[i][j] == temp) {
					isF = false;
					return isF;
				}
			}
		}
		return isF;
	}

	// 确定分区的起止坐标
	public static int[] partition(int ind) {
		int[] DX = new int[2];
		if (ind < 3) {
			DX[0] = 0;
			DX[1] = 2;
			return DX;
		} else if (ind < 6 && ind > 2) {
			DX[0] = 3;
			DX[1] = 5;
			return DX;
		} else {
			DX[0] = 6;
			DX[1] = 8;
			return DX;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值