ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

回溯搜索(数独)

2020-09-22 22:31:33  阅读:359  来源: 互联网

标签:P2 map int Next ++ markrow 搜索 回溯 数独


这是我以前写的,现在转存在博客上

玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3×3)内的数字均含1-9,不重复。

给出格子的行和列我们可以确定格子在哪一个宫

void cell(int x,int y)
{
     return x / 3 * 3 + y / 3;
}

我们只需要枚举其余所有的点

for(int map[][]=1;map[][]<10;map[][]++){
    if(check()){                              //每一层的check()是为了减少搜索次数的
        for(int map[][]=1;map[][]<10;map[][]++){  
            if(check()){
                for(int map[][]=1;map[][]<10;map[][]++){
                    if(check()){                          
                        ....                  //可以用递归实现 
                        ....                  //
                    }
                }
            }
        }
    }
}

这就是DFS,深度优先搜索

递归写法模板

//回溯法
void dfs(答案,搜索层数,其他参数){
    if(层数==maxdeep){
        更新答案;
        return;
    }
    (剪枝)
    for(枚举下一层可能的状态){ 
        if(check()){
              //更新全局变量表示状态的变量;
              //dfs(答案+新状态增加的价值,层数+1,其他参数);     
              //新状态必须是确定的,不能改变。
              //还原全局变量表示状态的变量;
        }
    }
}

构造标记数组

markrow[row][number];     //记录某一列是否存在某一个数字
markcol[col][number];        //记录某一行是否存在某一个数字
markbox[cell][number];      //记录某一宫是否存在某一个数字

这里需要注意深度搜索的顺序会很大程度的影响到算法的效率

代码

#include<iostream>
#include<algorithm>
#include<utility>
#include<cstdio>
#include<cstring>

using namespace std;

int map[9][9]; pair<int, int> Next[81];
int check = 0; // 已知的数的个数
int k = 0;  //递归的深度

int markrank[9][10];     //记录某一列是否存在某一个数字
int markrow[9][10];      //记录某一列是否存在某一个数字
int markcell[9][10];     //记录某一宫是否存在某一个数字

int cell(int x, int y)
{
      return x / 3 * 3 + y / 3;
}

// count函数用于记录(x,y)格子的还有几种可能情况
int count(int x, int y)
{
     int a[9] = { 0 }; int sum = 0;
     for (int i = 1; i <= 9; i++) {
         if (markrank[x][i] == 1 || markrow[y][i] == 1 || markcell[cell(x, y)][i] ==  1)
                a[i - 1] = 1;
      }
     for (int i = 0; i < 9; i++) {
          if (a[i] == 1) sum++;
     }
     return sum;
}

//next()函数的作用是求出当前可能情况最少的格子
pair<int, int> next() {
    pair<int, int> P2;
    int f = 0;
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
              if (map[i][j] == 0 && f == 1) {
                   if (count(P2.first, P2.second) < count(i, j))
                    {
                        P2.first = i; P2.second = j;
                    }
               }
               else if (map[i][j] == 0 && f == 0) {
                    P2.first = i; P2.second = j;
                    f++;
               }
        }
    }
    return P2;
}


void dfs(int x, int y)
{
    if (k == 81 - check) {
         for (int i = 0; i < 9; i++) {
               for (int j = 0; j < 9; j++) {
                       cout << map[i][j] << " ";
               }
               cout << endl;
         }
     }
    else {
        for (int i = 1; i < 10; i++) {
             if (markrank[x][i]==0 && markrow[y][i]==0 && markcell[cell(x,y)][i]==0){
                 map[x][y] = i;
                 markcell[cell(x, y)][i] = 1; markrank[x][i] = 1;  markrow[y][i] = 1;
                 k++;
                 if (Next[k].first == -1) {
                     pair<int, int> P = next();
                     Next[k] = P;
                 }
                 dfs(Next[k].first, Next[k].second);
                 k--;
                 markcell[cell(x, y)][i] = 0; markrank[x][i] = 0;  markrow[y][i] = 0;
             }
        }
    }
}
int
main()
{
     memset(markrank, 0, sizeof(markrank));
      memset(markrow, 0, sizeof(markrow));
     memset(markcell, 0, sizeof(markcell));
      memset(Next, -1, sizeof(Next));
      for (int i = 0; i < 9; i++) {
          for (int j = 0; j < 9; j++) {
                  scanf("%d", &map[i][j]);
                  if (map[i][j] != 0) check++;
                  markcell[cell(i, j)][map[i][j]] = 1;
                  markrank[i][map[i][j]] = 1;
                  markrow[j][map[i][j]] = 1;
           }
      }
      pair<int, int> P = next();
      dfs(P.first, P.second);
      return 0;
}

解决数独的其他算法:dancing links 算法

号称世界上最难的数独

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

标签:P2,map,int,Next,++,markrow,搜索,回溯,数独
来源: https://www.cnblogs.com/axchml/p/13715278.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有