数独1--暴力回溯法(时间超)

数独1--暴力回溯法(时间超)

一、心得

可用暴力搜索法(找唯一数单元格)和Dancing Links算法求解

先回顾之前的三篇文章

算法实践——数独的基本解法”,介绍求解数独的基本的暴力搜索法

跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”,网友huangfeidian介绍的求解数独的舞蹈链(Dancing Links)算法,这篇文章是介绍舞蹈链(Dancing Links)算法的。

算法实践——舞蹈链(Dancing Links)算法求解数独”,该文介绍了用舞蹈链(Dancing Links)算法求解数独,并给出了暴力破解法和舞蹈链(Dancing Links)算法之间的时间和空间占用效率的对比。

二、题目及分析

三、代码

时间超,未解决

  1 /*
  2 0 0 0 5 0 0 0 0 7
  3 4 8 0 0 0 6 3 2 0
  4 0 0 9 4 0 0 0 0 8
  5 5 0 0 3 0 7 0 0 0
  6 8 0 7 0 9 4 1 5 2
  7 2 9 6 8 1 0 0 0 4
  8 3 5 2 7 4 9 8 1 6
  9 7 4 0 1 6 3 2 9 0
 10 0 6 1 0 5 0 0 0 3
 11 算法:
 12 有点像八皇后问题
 13 每一列至少都有一个
 14 每一行至少有一个
 15 每一个3*3小方框里面至少有一个
 16
 17 总过有9列,c[i][j]==1表示第i列的数字j已经有了
 18 总过有9行,r[i][j]==1表示第i行的数字j已经有了
 19 总过有9行,q[i][j]==1表示第k(从上到小,从左到右)个3*3的框数字j已经有了
 20
 21 只能摆那些没有被数字占了的位置
 22
 23 优化1:1-9每个数字只能出现9次
 24 numTimes[i]表示数字i出现的次数
 25
 26
 27 */
 28
 29 #include <iostream>
 30 #include <cstring>
 31 using namespace std;
 32 int c[10][10],r[10][10],q[10][10];
 33 int num[10][10];
 34 int numTimes[10];
 35 int step=0;
 36
 37 void readDate(){
 38     for(int i=1;i<=9;i++){
 39         for(int j=1;j<=9;j++){
 40             int x;
 41             cin>>x;
 42             if(x){
 43                 step++;
 44                 numTimes[x]++;
 45                 num[i][j]=x;
 46                 r[i][x]=1;
 47                 c[j][x]=1;
 48                 //找到行列对应的小方框
 49                 int m=(i-1)/3*3;
 50                 int n=(j-1)/3;
 51                 int t=m+n+1;
 52                 q[t][x]=1;
 53             }
 54
 55         }
 56     }
 57 }
 58
 59 void printData(int a[10][10]){
 60     for(int i=1;i<=9;i++){
 61         for(int j=1;j<=9;j++){
 62             printf("%3d",a[i][j]);
 63         }
 64         cout<<endl;
 65     }
 66 }
 67
 68 void search(int step){
 69     if(step==82) {
 70         cout<<"--------------------------------------------------"<<endl;
 71         printData(num);
 72     }
 73     else{
 74         for(int n=1;n<=9;n++){//填1-9这9个数
 75             if(numTimes[n]==9) continue;
 76             for(int i=1;i<=9;i++){
 77                 for(int j=1;j<=9;j++){//i,j表示填num[i][j]位置的数
 78                     int m1=(i-1)/3*3;
 79                     int n1=(j-1)/3;
 80                     int t=m1+n1+1;//找i,j位置对应的方块
 81                     if(!num[i][j]&&!r[i][n]&&!c[j][n]&&!q[t][n]){
 82                         num[i][j]=n;
 83                         numTimes[n]++;
 84                         r[i][n]=1,c[j][n]=1,q[t][n]=1;
 85                         search(step+1);
 86                         //回溯
 87                         num[i][j]=0;
 88                         numTimes[n]--;
 89                         r[i][n]=0,c[j][n]=0,q[t][n]=0;
 90                     }
 91                 }
 92             }
 93         }
 94     }
 95 }
 96
 97 int main(){
 98     freopen("shudu.txt","r",stdin);
 99     readDate();
100     printData(num);
101     cout<<"--------------------------------------------------"<<endl;
102     printData(r);
103     cout<<"--------------------------------------------------"<<endl;
104     printData(c);
105     cout<<"--------------------------------------------------"<<endl;
106     printData(q);
107     cout<<"--------------------------------------------------"<<endl;
108     for(int i=1;i<=9;i++){
109         cout<<numTimes[i]<<endl;
110     }
111     cout<<step<<endl;
112     search(step+1);
113     cout<<"--------------------------------------------------"<<endl;
114
115 } 

时间: 2024-10-13 16:15:00

数独1--暴力回溯法(时间超)的相关文章

暴力回溯法 解八皇后

国际象棋 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. public class _8Queen { //回溯法,暴力解8皇后 private static int ways = 0; //返回解法个数 public static int f8queen() { int[][] board = new int

回溯法、数独与N阶可达问题(一)

回溯法是剪了枝的穷举,这是字面上的说法,不太好理解,不如讲解实例来的酸爽,于是引出了N阶可达问题: 有N个国家,每个国家有若干城市,小明要从中国(任意一个城市)出发,遍历所有国家(假设这个遍历顺序已经定了),最终到达美利坚(任意一个城市).而城市之间有可能不可达,只有小明尝试过才知道(就是后面的check()函数),求满足要求的一条路径? 从上面的表述中我们已经嗅到了浓浓的穷举屌丝气质——遍历所有组合,但是我们的回溯思想总是基于这样一个简单的事实:如果当前选择导致你走进了死胡同,那么这个选择一定

回溯法求解数独算法(C语言)

没有对输入的待解数独进行一般性验证(同一行.一列以及同一个小九宫格都不能出现重复数字) 算法利用回溯的思想: 从第一个空白处开始,找到其候选解(排除同行.同列以及同一小九宫格的所有出现过的数字,剩下未出现的数字都是候选解)的第一个值填入数独. 对第二个空白执行第一步(前面所填入的数字对此空白处有影响). 当出现某个空白的候选解个数为0时,就开始回溯,找到第一个候选解多于一个的,将其在使用的候选解设为不可取(本程序取值为-1),找到其下一个候选解,继续上面的步骤! 直到所有空白处填满,运算完成,输

python常用算法(7)——动态规划,回溯法

引言:从斐波那契数列看动态规划 斐波那契数列:Fn = Fn-1 + Fn-2    ( n = 1,2     fib(1) = fib(2) = 1) 练习:使用递归和非递归的方法来求解斐波那契数列的第 n 项 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # _*_coding:utf-8_*_ def fibnacci(n):     if n == 1

回溯法——装载问题

问题描述: 有一批共n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量是wi,且不能超,即Σwi<=c1+c2. 算法思想: --在给定的装载问题有解的情况下 最优装载方案: 首先将第一艘轮船尽可能的装满:  然后将剩余的集装箱装上第二艘轮船. 将第一艘轮船尽可能的装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近c1. 算法设计: 先考虑装载一艘轮船的情况,依次讨论每个集装箱的装载情况,共分为两种,要么装(1),要么不装(0),因此很明显其解空间树可以用子集树

回溯法 -数据结构与算法

1.回溯法算法思想: 定义: 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”. 1.回溯法适用:有许多问题,当需要找出它的解集(全部解)或者要求回答什么解是满足某些约束条件的最优解时,往往要使用回溯法. 2.有组织的穷举式搜索:回溯法的基本做法是搜索或者有的组织穷尽搜索.它能避免搜索所有的可能性.即避免不必要的搜索.这种方

回溯法浅谈

回溯法是初学者学习暴力法的第一个障碍,所谓回溯就是指当把问题分成若干步骤并递归求解时,如果当前步骤没有合法选择,则函数将返回上一级递归调用,这种现象称为回溯.正是因为这个原因,递归枚举算法常被称为回溯法,应用十分普遍. 八皇后问题 1 int tot=0; 2 int c[maxn]; //c[x]表示x行所在的列数 3 void dfs(int n,int cur){ 4 if(cur==n) ++tot; 5 for(int i=0;i<n;i++){ 6 int flag=0; 7 c[c

算法入门经典-第七章 例题7-4-1 拓展 n皇后问题 回溯法

实际上回溯法有暴力破解的意思在里面,解决一个问题,一路走到底,路无法通,返回寻找另   一条路. 回溯法可以解决很多的问题,如:N皇后问题和迷宫问题. 一.概念 回溯算法实际类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现不满足条件的时候,就回溯返回,尝试别的路径. 百度解释:回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯

leetcode_401_Binary Watch_回溯法_java实现

题目: A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom represent the minutes (0-59). Each LED represents a zero or one, with the least significant bit on the right. For example, the above binary watch