首页 > 试题广场 >

数独

[编程题]数独
  • 热度指数:1934 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
数独是一个非常有名的游戏。整个是一个9X9的大宫格,其中又被划分成9个3X3的小宫格。要求在每个小格中放入1-9中的某个数字。要求是:每行、每列、每个小宫格中数字不能重复。 现要求用计算机求解数独。(50分)

输入描述:
输入9行,每行为空格隔开的9个数字,为0的地方就是需要填充的数字。


输出描述:
输出九行,每行九个空格隔开的数字,为解出的答案。
示例1

输入

0 9 0 0 0 0 0 6 0
8 0 1 0 0 0 5 0 9
0 5 0 3 0 4 0 7 0
0 0 8 0 7 0 9 0 0
0 0 0 9 0 8 0 0 0
0 0 6 0 2 0 7 0 0
0 8 0 7 0 5 0 4 0
2 0 5 0 0 0 8 0 7
0 6 0 0 0 0 0 9 0

输出

7 9 3 8 5 1 4 6 2
8 4 1 2 6 7 5 3 9
6 5 2 3 9 4 1 7 8
3 2 8 4 7 6 9 5 1
5 7 4 9 1 8 6 2 3
9 1 6 5 2 3 7 8 4
1 8 9 7 3 5 2 4 6
2 3 5 6 4 9 8 1 7
4 6 7 1 8 2 3 9 5

import java.util.*;
public class Test{
    public static void main(String[] args){
        Scanner scanner=new Scanner(System.in);
        List<Set<Integer>> listRow=new ArrayList<Set<Integer>>();
        List<Set<Integer>> listCol=new ArrayList<Set<Integer>>();
        List<Set<Integer>> listGroup=new ArrayList<Set<Integer>>();
        int[][] Soduku=new int[9][9];
        for(int i=0;i<9;i++) {
            listRow.add(new TreeSet<Integer>());
            listCol.add(new TreeSet<Integer>());
            listGroup.add(new TreeSet<Integer>());
        }
        for(int i=0;i<9;i++) {
            for(int j=0;j<9;j++) {
                Soduku[i][j]=scanner.nextInt();
                listRow.get(i).add(Soduku[i][j]);
                listCol.get(j).add(Soduku[i][j]);
                listGroup.get(i/3*3+j/3).add(Soduku[i][j]);
            }
        }
        soduku(Soduku,listRow,listCol,listGroup,0);
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
            	if(j!=8) {
            		System.out.print(Soduku[i][j]+" ");
            	}else {
            		System.out.println(Soduku[i][j]);
            	} 
            } 
        }
    }
    public static Boolean soduku(int[][] Soduku,List<Set<Integer>> listRow,List<Set<Integer>> listCol,List<Set<Integer>> listGroup,int index){
    	Set<Integer> temp=new TreeSet<Integer>();
        Set<Integer> set1=new TreeSet<Integer>();
        Set<Integer> set2=new TreeSet<Integer>();
        int row=index/9;
        int col=index%9;
        int group=row/3*3+col/3;
//        System.out.println(index);
        if(index>80) {
        	return true;
        }
        for(int i=0;i<10;i++) {
        	temp.add(i);
        }
        if(Soduku[row][col]!=0) {
        	return soduku(Soduku, listRow, listCol, listGroup, index+1);
        }else {
        	set1.addAll(listRow.get(row));
        	set1.addAll(listCol.get(col));
        	set1.addAll(listGroup.get(group));
        	set2.addAll(temp);
        	set2.removeAll(set1);
        	if(set2.size()==0) {
        		return false;
        	}
//        	System.out.print(set2+"--->"+set2.size());
        	for(Iterator<Integer> it=set2.iterator();it.hasNext();) {
        		int t=it.next();
//        		System.out.println("-------->"+t);
//        		System.out.println(t);
        		Soduku[row][col]=t;
        		listRow.get(row).add(t);
        		listCol.get(col).add(t);
        		listGroup.get(row/3*3+col/3).add(t);
        		if(soduku(Soduku, listRow, listCol, listGroup, index+1)) {
        			return true;
        		}
//        		System.out.println(index+"------>"+t);
        		Soduku[row][col]=0;
        		listRow.get(row).remove(t);
        		listCol.get(col).remove(t);
        		listGroup.get(row/3*3+col/3).remove(t);
        	}
        	set1.clear();
        	set2.clear();
	        return false;
        }
    }
}

发表于 2020-03-19 17:43:23 回复(0)
import java.util.Scanner;
public class Main {
    private int[][] numMap = new int[9][9];
    private int staLen;
    private Coordinate[] stack = new Coordinate[81];

    public void run() {
        init();
        find(0);
    }
       //dfs
    private void find(int step) {
        if (step == staLen) {
                     //判断是否找到一个解
            show();
                     System.exit(0);
        } else {
            for (int i = 1; i <= 9; i++) {
               int x = stack[step].x;
               int y = stack[step].y;
                if (tryNum(x, y, i)) {
                    numMap[y][x] = i;
                                   find(step + 1);//若可填入,继续尝试下一个空
                    numMap[y][x] = 0;//回溯时把原来填的数字归0
                }
            }
        }
    }
       //判断坐标(x,y)能否填入num
    private boolean tryNum(int x, int y, int num) {
              //先判断同行同列有无重复
        for (int i = 0; i < 9; i++) {
            if (numMap[y][i] == num || numMap[i][x] == num) {
                return false;
            }
        }
              //分组判断
        x /= 3;
        y /= 3;
        for (int i = y * 3; i < y * 3 + 3; i++) {
            for (int j = x * 3; j < x * 3 + 3; j++) {
                if (numMap[i][j] == num) {
                    return false;
                }
            }
        }
        return true;
    }
       //初始化读入数据
    private void init() {
              Scanner sc = new Scanner(System.in);
        for (int y = 0; y < 9; y++) {
            for (int x = 0; x < 9; x++) {
                numMap[y][x] = sc.nextInt();
                if (numMap[y][x] == 0) {
                    stack[staLen++] = new Coordinate(x, y);
                }
            }
        }
        sc.close();
    }
       //输出
    private void show() {
        for (int y = 0; y < 9; y++) {
            for (int x = 0; x < 9; x++) {
                               //每行第一个数字前面没有空格
                if(x == 0){
                    System.out.print(numMap[y][x]);
                }else{
                    System.out.print(" " + numMap[y][x]);
                }
            }
            System.out.println();
        }
    }
       //坐标类
    static class Coordinate {
        int x;
        int y;
        Coordinate(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    
    public static void main(String[] args){
        new Main().run();
    }
} 
先把所有的0坐标用数组存起来,然后深度优先搜索
编辑于 2018-01-08 11:13:26 回复(0)