蓝桥杯 数独 回溯法 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

思路:
总体思路:从数字的第一个位置开始,按照从左到右、从上到下的顺序逐个填入数字。
单个单元格思路:首先进行判断,若已有数字则寻找下一单元格,若无数字则进行 行、列以及宫内是否重复的判断,若重复则value++,若不重复则填入数字并进入下一单元格。 PS:当循环结束时仍没有满足操作的数字即(1~9)都不能填入该单元格即上一单元格填入的数字错误,则回溯到上一个单元格重新填入数字。

回溯法的要点:
1、回溯法是为了求解,这个解可能是一个也有 可能是很多个,所以其过程是有序的。
2、当前步骤无法求解时要能够回到上一步骤。
3、在进行回溯时要将前一步骤的数据操作清空。

代码如下(详细备注):

import java.util.Scanner;
public class sudoku {
    static int qipan[][]=new int[9][9];
    		public static void main(String[] args) {
    			Scanner scanner=new Scanner(System.in);  			
    			//棋盘输入
    			for(int i=0;i<9;i++)
    			{
    				String line=scanner.nextLine();
    				for(int j=0;j<9;j++)
    				{
    					qipan[i][j]=line.charAt(j)-'0';
    				}
    			}
    	
    			//起始--向棋盘中填入数字
    			play(0, 0);	
    		}
    		
    		//向第row行line列填入数字
    		public static void play(int row,int line)
    		{
    			if(row==9) //当数字填满时打印输出
    			{
    				print();
    				return; //打印后退出程序
    			}
    				
    			if(qipan[row][line]==0)   //当前单元格中没有数字
    			{	
        			for(int value=1;value<10;value++)
        			{
        				if(checkg(row, line, value)!=0&&checkrl(row, line, value)!=0) //分别进行行列检测和宫内检测
        				{
        					
        					qipan[row][line]=value;      //通过检测,将数字i填入单元格
        
        	        		   //输入下一个空格数字
        	        		   if(line<8)  play(row, line+1);
        	        		   else if(row<9&&line==8)  play(row+1, 0);
        	        		   
        	        		 //回溯   该点填入的数字错误  进行重置并尝试下一个未重复数字
        	        		   qipan[row][line]=0;  	
            			}
        				
        			}
        			
    			}else //当前单元格中有数字,寻找下一单元格
    			{
    				if(line<8)  play(row, line+1);
  	    		   else if(row<9&&line==8)  play(row+1, 0);
				} 
    		}
    		
    		//宫内检测
    		public static int checkg(int row,int line,int value)
    		{
    			if(row>=0&&row<=2)  row=0;
    			if(row>=3&&row<=5)  row=3;
    			if(row>=6&&row<=8)  row=6;
    			if(line>=0&&line<=2) line=0;
    			if(line>=3&&line<=5) line=3;
    			if(line>=6&&line<=8) line=6;
    			
    			for(int i=row;i<row+3;i++)
    			{
    				for(int j=line;j<line+3;j++)
    				{
    				//	System.out.println(i+" "+j);
    					if(qipan[i][j]==value)    //有重复数字
    					{
    						return 0;
    					}	
    				}
    			}
    			
    			return 1;   //无重复数字
    		}
    		
    		//行列检测
    		public static int checkrl(int row,int line,int value)
    		{
    			for(int i=0;i<9;i++)
    			{
    				if(qipan[row][i]==value||qipan[i][line]==value) //行或列中有重复的数字
    					return 0;
    			}
    			return 1;
    		}
    
    		//打印
    		public static void print()
    		{
    			for(int i=0;i<9;i++)
    			{
    				for(int j=0;j<9;j++)
    				{
    					System.out.print(qipan[i][j]);
    				}
    				System.out.println();
    			}
    		}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值