回溯法 --数独

蓝桥杯——数独JAVA

这几天开始在准备蓝桥杯了,想借此来学习一下算法,提高自己编程的能力,前几天看的一个数独题,虽然知道是用深度优先去做,但是在做的时候还是遇到了些问题,但是感觉回溯算法做题时是有一点套路的,所以决定写下来。

题目:

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

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

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

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

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

例如:
输入(即图中题目):
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700

程序应该输出:
145327698
839654127
672918543
496185372
218473956
753296481
367542819
984761235
521839764

再例如,输入:
800000000
003600000
070090200
050007000
000045700
000100030
001000068
008500010
090000400

程序应该输出:
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452

在这里插入图片描述

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

思路:

首先这题一看就是回溯法,来分析一下这个算法的实现,首先定义一个全局的二维数组,数组长度为9即可,然后在主函数中输入二维数组数据。然后就开始调用这里面最重要的函数get(int row,int col)row:行下标,col:列下标。
但凡是数组用到了回溯,基本这个函数里的参数都是下标(题目做的还不是很多,只能说目前是这样),然后函数里当超过数组下标值立即将数组输出或者执行其他操作,然后进行判断,这题里当数组值为0时,说明这个位置没有数填进去,那么进行1–10的遍历,开始放值,放值之前要判断这个数是否和所在行,列,以及同色九宫内的数重复(这里用is_row_col(int row,int col,int target)函数和is_nine(int row,int col,int target)函数进行判断),如果返回值都是true,那么进行赋值操作,并且向下一个数组元素递归,当遇到重复值,将数组元素值置0,回溯。

代码

import java.util.Scanner;

public class Main {

   private static int[][] data = new int[9][9];
   
   public static void print() {
   	int t=0;
   	for(int i=0;i<9;i++) {
   		for(int j=0;j<9;j++) {
   			System.out.print(data[i][j]);
   			t++;
   			if(t==9) {
   				System.out.println();
   				t=0;
   			}
   		}
   	}
   }
   
   public static boolean is_row_col(int row,int col,int target) {
   	boolean test=true;
   	for(int i=0;i<9;i++) {
   		if(data[row][i]==target) {
   			test=false;
   			break;
   		}  
   		if(data[i][col]==target) {
   			test=false;
   			break;
   		}  
   	}
   	
   	return test;
   }
   
   public static boolean is_nine(int row,int col,int target) {
   	boolean test=true;
   	int row_min=0;
   	int row_max=0;
   	int col_min=0;
   	int col_max=0;
   	
   	if(row>=0&&row<=2) {
   		row_min=0;
   		row_max=2;
   	}
   	if(row>=3&&row<=5) {
   		row_min=3;
   		row_max=5;
   	}
   	if(row>=6&&row<=8) {
   		row_min=6;
   		row_max=8;
   	}
   	if(col>=0&&col<=2) {
   		col_min=0;
   		col_max=2;
   	}
   	if(col>=3&&col<=5) {
   		col_min=3;
   		col_max=5;
   	}
   	if(col>=6&&col<=8) {
   		col_min=6;
   		col_max=8;
   	}
   			
   	
   	
   	for(int i=row_min;i<=row_max;i++) {
   		for(int j=col_min;j<=col_max;j++) {
   			if(data[i][j]==target) {
   				 test=false;
   				 break;
   			}
   		}
   	}
   	
   	return test;
   }
   
   public static void get(int row,int col) {
   	if(row>=9) {
   		print();
   		System.exit(0);
   	}
   	
   	if(data[row][col]==0) {
   		for(int t=1;t<10;t++) {
   			if(is_row_col(row,col,t)&&is_nine(row,col,t)){
   				data[row][col]=t;
   				get(row+(col+1)/9,(col+1)%9);//继续向下递归
   			}
   			
   			data[row][col]=0;//回溯
   		}
   		
   	}else {
   		get(row+(col+1)/9,(col+1)%9);
   	}
   }
   
   public static void main(String[] args) {
   	Scanner s = new Scanner(System.in);
   	
   	for(int i=0;i<9;i++) {
   		String ss = s.nextLine();
   		for(int j=0;j<9;j++) {
   			data[i][j]=Integer.parseInt(ss.charAt(j)+"");
   		}
   	}
   	
   	
   	get(0,0);
   	
   	
   }
}

欢迎指出问题!

猜你喜欢

转载自blog.csdn.net/qq_37438740/article/details/84573369