zoukankan      html  css  js  c++  java
  • java实现拉丁方块填数字

    “数独”是当下炙手可热的智力游戏。一般认为它的起源是“拉丁方块”,是大数学家欧拉于1783年发明的。

    如图[1.jpg]所示:6x6的小格被分为6个部分(图中用不同的颜色区分),每个部分含有6个小格(以下也称为分组)。
    
    开始的时候,某些小格中已经填写了字母(ABCDEF之一)。需要在所有剩下的小格中补填字母。
    
    全部填好后,必须满足如下约束:
    
    1. 所填字母只允许是A,B,C,D,E,F 中的某一个。
    
    2. 每行的6个小格中,所填写的字母不能重复。
    
    3. 每列的6个小格中,所填写的字母不能重复。
    
    4. 每个分组(参见图中不同颜色表示)包含的6个小格中,所填写的字母不能重复。
    
    为了表示上的方便,我们用下面的6阶方阵来表示图[1.jpg]对应的分组情况(组号为0~5):
    

    022013
    243333
    445555

    用下面的数据表示其已有字母的填写情况:
    

    02C
    03B
    05A
    20D
    35E
    53F

    很明显,第一列表示行号,第二列表示列号,第三列表示填写的字母。行号、列号都从0开始计算。
    
    一种可行的填写方案(此题刚好答案唯一)为:
    

    E F C B D A
    A C E D F B
    D A B E C F
    F B D C A E
    B D F A E C
    C E A F B D

    你的任务是:编写程序,对一般的拉丁方块问题求解,如果多解,要求找到所有解。
    

    【输入、输出格式要求】

    用户首先输入6行数据,表示拉丁方块的分组情况。

    接着用户输入一个整数n (n<36), 表示接下来的数据行数

    接着输入n行数据,每行表示一个预先填写的字母。

    程序则输出所有可能的解(各个解间的顺序不重要)。
    每个解占用7行。

    即,先输出一个整数,表示该解的序号(从1开始),接着输出一个6x6的字母方阵,表示该解。

    解的字母之间用空格分开。

    如果找不到任何满足条件的解,则输出“无解”

    例如:用户输入:
    

    022013
    243333
    445555
    02C
    03B
    05A
    20D
    35E
    53F

    则程序输出:
    

    E F C B D A
    A C E D F B
    D A B E C F
    F B D C A E
    B D F A E C
    C E A F B D

    再如,用户输入:
    002113
    022443
    555553
    04B
    05A
    13D
    14C
    24E
    50C
    51A
    则程序输出:
    D C E F B A
    E F A D C B
    A B F C E D
    B E D A F C
    F D C B A E
    C A B E D F
    D C E F B A
    E F A D C B
    A D F B E C
    B E C A F D
    F B D C A E
    C A B E D F
    D C F E B A
    A E B D C F
    F D A C E B
    B F E A D C
    E B C F A D
    C A D B F E
    D C F E B A
    B E A D C F
    A D C F E B
    F B E A D C
    E F B C A D
    C A D B F E
    D C F E B A
    E F A D C B
    A B C F E D
    B E D A F C
    F D B C A E
    C A E B D F
    D C F E B A
    E F A D C B
    A B D F E C
    B E C A F D
    F D B C A E
    C A E B D F
    D C F E B A
    E F A D C B
    A D B F E C
    B E C A F D
    F B D C A E
    C A E B D F
    D C F E B A
    F E A D C B
    A D B C E F
    B F E A D C
    E B C F A D
    C A D B F E
    D C F E B A
    F E A D C B
    A F C B E D
    B D E A F C
    E B D C A F
    C A B F D E

    package com.liu.ex9;
    
    import java.util.HashSet;
    import java.util.Scanner;
    
    public class Main {
        public static int[][] group = new int[6][6];   //输入分组情况
        public static char[][] result = new char[6][6];  //满足题意的填充结果
        public static int[][] row = new int[6][6];  //检测6行是否均为不同字母
        public static int[][] col = new int[6][6];  //检测6列是否均为不同字母
        public static int[][] set = new int[6][6];  //检测0~5组是否均为不同字母
        public static char[] value = {'A','B','C','D','E','F'};  //填充字母
        public static int count = 0;   //统计最终解个数
        public HashSet<String> hash = new HashSet<String>();
        
        public boolean check() {
            StringBuilder temp = new StringBuilder("");
            for(int i = 0;i < 6;i++) {
                for(int j = 0;j < 6;j++) 
                    temp.append(result[i][j]+" ");
                  temp.append("
    ");
            }
            String A = temp.toString();
            if(hash.contains(A))
                return false;
            return true;
        }
        
        public void dfs(int step) {
            if(step >= 37) {
                if(check()) {  //检测是否有重复解
                    count++;
                    System.out.println(count);
                    StringBuilder temp = new StringBuilder("");
                    for(int i = 0;i < 6;i++) {
                        for(int j = 0;j < 6;j++) 
                            temp.append(result[i][j]+" ");
                          temp.append("
    ");
                    }
                    hash.add(temp.toString());
                    System.out.print(temp);
                }
                return;
            } else {
                int tempRow = (step - 1) / 6;
                int tempCol = (step - 1) % 6;
                int tempSet = group[tempRow][tempCol];
                for(int i = 0;i < 6;i++) {
                    if(result[tempRow][tempCol] == '-') {
                        char temp = (char) ('A' + i);
                        if(row[tempRow][i] == 0 && col[tempCol][i] == 0 && set[tempSet][i] == 0) {
                            result[tempRow][tempCol] = temp;
                            row[tempRow][i] = 1;
                            col[tempCol][i] = 1;
                            set[tempSet][i] = 1;
                            dfs(step + 1);
                            result[tempRow][tempCol] = '-';  //回溯处理
                            row[tempRow][i] = 0;
                            col[tempCol][i] = 0;
                            set[tempSet][i] = 0;
                            
                        } else {
                            continue;
                        }
                    } else {
                        dfs(step + 1);
                    }
                }
            }
            return;
        }
        
        
        public static void main(String[] args) {
            Main test = new Main();
            for(int i = 0;i < 6;i++)
                for(int j = 0;j < 6;j++)
                    result[i][j] = '-';  //初始化为填充格子字符为'-'
            Scanner in = new Scanner(System.in);
            for(int i = 0;i < 6;i++) {
                String temp = in.nextLine();
                for(int j = 0;j < 6;j++)
                    group[i][j] = temp.charAt(j) - '0';
            }
            int n = in.nextInt();
            in.nextLine();
            for(int i = 0;i < n;i++) {
                String temp = in.nextLine();
                int a = temp.charAt(0) - '0';
                int b = temp.charAt(1) - '0';
                int v = temp.charAt(2) - 'A';
                result[a][b] = temp.charAt(2);
                row[a][v] = 1;    //表示第a行位于第v个的位置,已经填充
                col[b][v] = 1;    //表示第b列位于第v个的位置,已经填充
                int tempSet = group[a][b];   //获取(a,b)小组组号
                set[tempSet][v] = 1;   //表示第tempSet小组第v个位置,已经填充
            }
            test.dfs(1);
        }
    }
    
  • 相关阅读:
    Google 商店:您的应用静态链接到的 OpenSSL 版本有多个安全漏洞。建议您尽快更新 OpenSSL
    android控件库(2)-仿Google Camera 的对焦效果
    新浪微博客户端(54)-代码重构-将宏定义修改为常量
    android自定义控件(1)-自定义控件属性
    新浪微博客户端(53)-记录用户最近点击表情
    android-解决EditText的inputType为Password时, 字体不一致的问题
    新浪微博客户端(52)-长按或滑动显示表情
    iOS- Terminating app due to uncaught exception 'NSRangeException'
    新浪微博客户端(51)-将表情图片转换为文本
    新浪微博客户端(50)-解决输入Emotion表情逐渐变小的问题
  • 原文地址:https://www.cnblogs.com/a1439775520/p/13078227.html
Copyright © 2011-2022 走看看