[Java] POJ 2676

一、思路

dfs进行试探,如果失败就进行回溯,若找到一组解就进行返回最后输出。

进行剪枝:

  • 利用3个数组进行判断在某行某列某方格中 这个数到底被标记没有,如果别标记那么就不能选这个数。
  • 特别注意的是如何对3*3的小方格里面的1-9进行标记
  1. 首先我们将大方格分成9个3*3的小方格
    在这里插入图片描述
  2. i,j代表在大方格中的位置,下标从0到8, 我们让a=i/3, b = j /3
    在这里插入图片描述
    在这里插入图片描述

可以从图中得出 K = 3 * a + b = 3 * (i / 3) + j / 3;
这就是3*3小方格的下标,我们就可将9个3*3的小方格里面的1-9进行标记

二、代码

import java.util.Scanner;

public class POJ_2676 {
	static int t;
	static int[][] G = new int[10][10];
	static boolean[][] row = new boolean[10][10]; //row[i][x] 代 表第i行的x被标记没有  true为被标记 
	static boolean[][] col = new boolean[10][10]; //col[i][x] 代 表第i列的x被标记没有 
	static boolean[][] grid = new boolean[10][10]; //grid[k][x] 代 表第k个3*3的小格子的x被标记没有 
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		t = sc.nextInt(); 
		while (t-- > 0) {
			clear();//清空下row col grid ok
			for (int i = 0; i < 9; i++) {
				String str = sc.next();
				for (int j = 0; j < 9; j++) {
					G[i][j] = str.charAt(j) - '0';
					if (G[i][j] != 0) {
						//进行标记
						int k = 3 *(i / 3) + j / 3; 
						row[i][G[i][j]] = true;
						col[j][G[i][j]] = true;
						grid[k][G[i][j]] = true;
					}
				}
			}
			dfs(0,0);
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++) {
					System.out.print(G[i][j]);
				}
				System.out.println();
			}
		}
	}
	static boolean ok; //查看是否找到一种可能
	static void dfs(int x, int y) {
		if (x == 9) {
			ok = true; //找到一组解
			return; //已经到第10行了 超出了
		}
		
		if (G[x][y] != 0){
			//代表该位上已经有数,直接搜下一个
			if (y + 1 == 9) {
				dfs(x + 1,0);
			} else {
				dfs(x, y + 1);
			}
		} else {
			//k代表第几个方格
			int k = 3 * (x / 3) + y / 3;
			//枚举 1-9 这个9个数 看那个能放在这个位置上
			for (int i = 1; i <= 9; i++) {
				if (!row[x][i] && !col[y][i] && !grid[k][i]) {
					//3个条件都满足
					G[x][y] = i;
					row[x][i] = true;
					col[y][i] = true;
					grid[k][i] = true;
					if (y + 1 == 9) {
						dfs(x + 1,0);
					} else {
						dfs(x, y + 1);
					}
					if (ok) return; //如果找到一组解 就不回溯
					//回溯
					G[x][y] = 0;
					row[x][i] = false;
					col[y][i] = false;
					grid[k][i] = false;
				}
			}
		}
		
	}
	
	static void clear() {
		for (int i = 0; i <= 9; i++) {
			for (int j = 0; j <= 9; j++) {
				ok = false;
				row[i][j] = false;
				col[i][j] = false;
				grid[i][j] = false;
				G[i][j] = 0; //注意清空下原图
			}
		}
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值