日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数独问题 解数独

發布時間:2024/1/8 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数独问题 解数独 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數獨是一個非常有名的游戲。整個是一個9X9的大宮格,其中又被劃分成9個3X3的小宮格。要求在每個小格中放入1-9中的某個數字。要求是:每行、每列、每個小宮格中數字不能重復。 現要求用計算機求解數獨。

輸入描述:

輸入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


解法一:利用DFS進行狀態搜索(搜到一種就輸出)

#include<bits/stdc++.h> using namespace std;int a[9][9]; int sum=0; bool sign=false;//只能輸出第一次搜索出的正確結果 bool check(int key,int n){//檢查行int j=n/9; for(int i=0;i<9;i++)if(a[j][i]==key) return false;//檢查列 j=n%9;for(int i=0;i<9;i++) {if(a[i][j]==key)return false;}//檢查九個小方塊int x=n/9;//n的行坐標int y=n%9;//n的列坐標//***最重要的技巧*** x=x/3*3;y=y/3*3; //x和y是n所在的小方塊最左上角的坐標 for(int i=x;i<x+3;i++)for(int j=y;j<y+3;j++)if(a[i][j]==key)return false; return true; } int DFS(int n){//把棋盤標號,n是二維棋盤的一維序號 if(n>80){//此時說明找到了 sign=true;//信號量 說明找到了 return 0;}if(a[n/9][n%9]!=0){DFS(n+1);}else{for(int i=1;i<=9;i++){if(check(i,n)){a[n/9][n%9]=i;if(n<=80) DFS(n+1);//這個if用于在找到一種解法之后的回溯過程中防止棋盤復原 /* if(sign){return 0; } *///只有沒找到的情況才回溯,如果不加下面的if語句,在遞歸回退的過程中填好的空又變回去了 if(sign==false) a[n/9][n%9]=0;//回溯 }} } return 0; } int main() {for(int i=0;i<9;i++)for(int j=0;j<9;j++) cin>>a[i][j];DFS(0); //不一定必有解,先按必有解的情況輸出 cout<<"******************"<<endl;for(int i=0;i<9;i++){for(int j=0;j<9;j++)cout<<a[i][j]<<' '; cout<<endl; }return 0;}

解法二:利用DFS搜索所有結果

#include<bits/stdc++.h> using namespace std;int a[9][9]; int sum=0; int s=0; int t=0;//輸出所有正確結果或無結果的情況 bool check(int key,int n){//行int j=n/9; for(int i=0;i<9;i++)if(a[j][i]==key) return false;//列 j=n%9;for(int i=0;i<9;i++) {if(a[i][j]==key)return false;}//九個小方塊int x=n/9;//n的行坐標int y=n%9;//n的列坐標//最重要的技巧 x=x/3*3;//n所在的小方塊最左上角的坐標 y=y/3*3; for(int i=x;i<x+3;i++)for(int j=y;j<y+3;j++)if(a[i][j]==key)return false; return true; } void shuchu(){t++; cout<<"******************"<<endl;for(int i=0;i<9;i++){for(int j=0;j<9;j++)cout<<a[i][j]<<' '; cout<<endl; } } int DFS(int n){s++;if(n>80){sum++;shuchu();cout<<sum<<endl; return 0;}if(a[n/9][n%9]!=0){DFS(n+1);}else{for(int i=1;i<=9;i++){if(check(i,n)){a[n/9][n%9]=i;DFS(n+1);//shuchu();a[n/9][n%9]=0;//回溯 }} } return 0; } int main() { // freopen("sample.out","w",stdout);for(int i=0;i<9;i++)for(int j=0;j<9;j++) cin>>a[i][j];DFS(0); //不一定必有解,先按必有解的情況輸出 cout<<"答案數:"; cout<<sum<<endl;cout<<"進入DFS次數:"; cout<<s<<endl; cout<<"輸出次數:";cout<<t<<endl; // fclose(stdout);return 0;}

解法三:利用解法二找出所有數獨存在的結果,然后在結果中搜索符合給出的數獨空缺條件的。
在解法二中輸入

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

會搜索出 M種結果并保存起來,寫個程序在這些結果中搜索即可。在搜索時應該注意優化。
這個M看起來有點大啊,已經跑到200w了還沒結束。

一個技巧:
假設搜索庫有M個數獨結果,待填數獨有N個數已知,即有N個條件(數獨中的非0數即為條件),那么有復雜度為O(M+N)和O(MN)的兩種算法。
O(M+N)的方法:
依次拿著N個條件在M個結果的結果庫中搜索,因為搜索出來的結果在一定順序上是從小到大的,因此可以在第a個條件在結果庫中找到后,繼續用第a+1個條件在后面的結果庫中搜索。若所有條件都用光了,那么從最后一個條件搜索到的第一個結果到結果庫的最后一個結果都是符合條件的數獨。
O(MN)的方法:
遍歷結果庫然后在遍歷過程中匹配所有的條件,若符合所有的條件就輸出。

這個搜索的方法好像不大行啊!!!

總結

以上是生活随笔為你收集整理的数独问题 解数独的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。