數獨求解(c語言以及python)
/* ============================================================================ Name : sudoku.c Author : Joey Version : Copyright : UESTC Description : Try to solve sudoku puzzle. 1.0 2010年10月27日20:28:13 Create 1.1 2010-11-9 19:03:22 modify 輸入引數:儲存數獨棋盤格局的檔名 檔案的資料是9*9的矩陣,每個數的取值範圍為0-9 0表示該位置對應棋盤上的資料位空 1-9代表該位置對應的數 如果不提供輸入引數,程式會以互動式的方式請求使用者指定一個檔名。 ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include <string.h> //#include <time.h> //#define _DEBUG /*除錯開關*/ #define MAX_FILE_NAME_LEN 30 /*檔名字串最大長度*/ #define BOARD_SIZE 9 /*棋盤大小*/ #define BLOCK_SIZE 3 /*每塊區域大小*/ #define VALID_MASK 0x03FE /*倒數第2位至倒數10位為有效標誌位*/ /** * 這些巨集定義用於將標誌位置位或者清除 */ #define setblockbit(rowidx,colidx,a) (blockbits[rowidx/3][colidx/3] |= 1<<a) #define clearblockbit(rowidx, colidx, a) (blockbits[rowidx/3][colidx/3] &= ~(1<<a)) #define testblockbit(rowidx, colidx, a) (blockbits[rowidx/3][colidx/3] & (1<<a) & VALID_MASK) #define setrowbit(rowidx,a) (rowbits[rowidx] |= 1<<a) #define clearrowbit(rowidx,a) (rowbits[rowidx] &= ~(1<<a)) #define testrowbit(rowidx, a) (rowbits[rowidx] & (1<<a) &VALID_MASK) #define setcolumnbit(colidx,a) (columnbits[colidx] |= 1<<a) #define clearcolumnbit(colidx,a) (columnbits[colidx] &= ~(1<<a)) #define testcolumnbit(colidx,a) (columnbits[colidx] & (1<<a) & VALID_MASK) /** * 位置型別 */ typedef struct Coodinate_T{ int row; int column; }Coordinate; typedef struct Stkelemnt_T{ int idx; int number; }Stkelement; int board[BOARD_SIZE][BOARD_SIZE];/*儲存棋盤資料*/ unsigned short blockbits[BLOCK_SIZE][BLOCK_SIZE];/*儲存9個3*3方塊的資料狀態*/ unsigned short rowbits[BOARD_SIZE]; /*儲存每一行資料狀態*/ unsigned short columnbits[BOARD_SIZE]; /*儲存每一列的資料狀態*/ Coordinate blanklist[BOARD_SIZE*BOARD_SIZE]; /*儲存了待填寫等方格位置*/ int blanknum = 0; /*待填寫方格總個數*/ /************************************/ /* Internal struct for DFS algorithm*/ Stkelement stk[300]; int top = 0; /***********************************/ void trysolve(FILE *fp); int loadAndCheckInitBoard(FILE *fp); int searchAns(int row, int column, int from); int solve(); void pushstk(int blankidx, int num); Stkelement popstk(); void outputresult(); #ifdef _DEBUG void printstk(); #endif /** *程式入口,第一個執行引數為輸入檔案檔名,若不存在,從控制檯中互動獲取檔名 */ int main(int argc, char** argv) { char filename[MAX_FILE_NAME_LEN]; FILE *fp = NULL; if (argc <= 1){ printf("input file name:"); scanf("%s",filename); }else{ strcpy(filename, argv[1]); } fp = fopen(filename,"r"); if (fp == NULL){ fprintf(stderr,"Error occurred when open file %s", filename); exit(EXIT_FAILURE); } trysolve(fp); fclose(fp); return EXIT_SUCCESS; } /** * 輸入: * row:格子的行 * column:格子的列 * from:從該數開始遞增查詢 * 輸出:返回值為 * 0:未找到 * 1-9:找到的可行解 */ int searchAns(int row, int column, int from){ int number = from; if (number > 9 || number < 1){ //起始值過大或過小 return 0; } while (number <= 9){ if (testblockbit(row, column, number)==0 && testrowbit(row, number)==0 && testcolumnbit(column, number)==0){ return number; }else number++; } return 0; /*未找到*/ } /** * 從fp指向的檔案中讀取初始棋盤,嘗試解決數獨問題 */ void trysolve(FILE *fp){ int rt = loadAndCheckInitBoard(fp); if (1 == rt){ printf("Initial board isn't correct!\n"); }else if (2 == rt ){ printf("Invalid data was contented in the file!\n"); }else if (3== rt){ printf("資料不完整\n"); }else{ printf("Load board successfully, try to solve...\n"); if (solve() == 0){ printf("Success, result:\n"); outputresult(); }else{ printf("The puzzle can't be solved\n"); } } return; } /** * 載入初始棋盤並對數獨棋盤的可解性做初步檢查,棋盤有效資料為0-9,大小為9*9 * fp: * 已開啟的檔案指標 * 返回值: * 0:成功讀取9*9棋盤 * 1:初始棋盤不合規則 * 2:檔案中包含無效資料 * 3:資料不完整 */ int loadAndCheckInitBoard(FILE *fp){ int a; int idx = 0; int rowidx = 0; int columnidx = 0; Coordinate cood; while(fscanf(fp, "%d", &a) != EOF){ rowidx = idx / 9; /*行數*/ columnidx = idx % 9; /*列數*/ if (a >= 1 && a <= 9){ /*如果是已填格子*/ if (testblockbit(rowidx,columnidx,a) == 0 && testcolumnbit(columnidx,a) == 0 && testrowbit(rowidx, a) == 0){ setblockbit(rowidx, columnidx, a); setrowbit(rowidx, a); setcolumnbit(columnidx, a); }else{ return 1; /*初始棋盤本身有錯*/ } }else if (a == 0){ /*如果是待填格子,記錄下待填格子的座標*/ cood.row = rowidx; cood.column = columnidx; blanklist[blanknum++] = cood; }else{ return 2; /*發現無效資料*/ } board[rowidx][columnidx] = a; idx++; } /*資料不夠,格式錯誤*/ if (idx != BOARD_SIZE * BOARD_SIZE){ return 3; } return 0; /*載入成功*/ } /** * 遞迴求解數獨問題,呼叫前初始資料已被正確讀取, * 返回值: * 0:找到一個可行解 * 1:未找到可行解 */ int solve(){ int fillidx = 0; /*fill index in blanklist*/ int ans = 0; Stkelement curcell; pushstk(fillidx, ans); /*初始入棧的值*/ while (top != 0){ /*棧不為空*/ #ifdef _DEBUG printstk(); #endif curcell = popstk(); ans = curcell.number; fillidx = curcell.idx; ans = searchAns(blanklist[fillidx].row, blanklist[fillidx].column, ans+1); while(ans != 0){ pushstk(fillidx, ans); #ifdef _DEBUG printstk(); #endif if (fillidx == blanknum-1){ return 0; /*找到了一個可行解*/ } fillidx++; ans = searchAns(blanklist[fillidx].row, blanklist[fillidx].column, 1); } } return 1; /*無解*/ } /** * 將blankidx對應的座標壓入棧中,並根據該位置上的數字將相應的bit置位 */ void pushstk(int blankidx, int num){ /*set bits*/ setblockbit(blanklist[blankidx].row, blanklist[blankidx].column, num); setrowbit(blanklist[blankidx].row, num); setcolumnbit(blanklist[blankidx].column, num); /*push into stack*/ Stkelement ele = {blankidx, num}; stk[top++] = ele; return ; } /** * 彈出棧頂的元素,並將該元素對應的bit清楚 */ Stkelement popstk(){ Stkelement ele = stk[--top]; /*clear bits*/ clearblockbit(blanklist[ele.idx].row, blanklist[ele.idx].column, ele.number); clearrowbit(blanklist[ele.idx].row, ele.number); clearcolumnbit(blanklist[ele.idx].column, ele.number); /**/ return ele; } #ifdef _DEBUG void printstk(){ int i = top-1; printf("***********Stack trace************\n"); for (;i >= 0; i--){ printf("%dth row:%d column:%d number:%d\n", i, blanklist[stk[i].idx].row, blanklist[stk[i].idx].column, stk[i].number); } printf("**********************************\n"); fflush(stdout); } #endif /** * 輸出結果至標準輸出裝置 */ void outputresult(){ int r,c; int i = 0; for (;i < top; i++){ board[blanklist[stk[i].idx].row][blanklist[stk[i].idx].column] = stk[i].number; } for (r = 0; r < BOARD_SIZE; r++){ for (c = 0; c < BOARD_SIZE; c++){ printf("%d ",board[r][c]); } printf("\n"); } fflush(stdout); }
Python版的
#coding=utf-8 ''' Created on 2011-11-29 解決8皇后問題 廣搜演算法 @author: Joey ''' import copy def solve(): queue = [] for i in range(8): queue.append([(0,i)]) results = [] max = 0 while len(queue) > 0: poslist = queue.pop(0) lastrow = poslist[-1][0] assert lastrow < 7 for col in range(0,8): if islegal((lastrow+1,col), poslist): poslstcpy = copy.deepcopy(poslist) poslstcpy.append((lastrow+1,col)) if len(poslstcpy) == 8: results.append(poslstcpy) else: queue.append(poslstcpy) if len(queue) > max: max = len(queue) print max print len(results) for item in results: printresul(item) def islegal(pos, poslist): for xpos in poslist: if xpos[0] == pos[0] or xpos[1] == pos[1] \ or abs(xpos[0]-pos[0]) == abs(xpos[1]-pos[1]): return False return True def printresul(poslist): for row in range(8): for col in range(8): if (row,col) in poslist: print 'o', else: print '.', print ' ' print '--------' solve()
相關推薦
數獨求解(c語言以及python)
/* ============================================================================ Name : sudoku.c Author : Joey Version
數獨 遞迴求解(C語言)
遞迴求解數獨(C語言) 本程式採用c語言編寫,作用是獲得一個數獨的解。 經測試,計算普通數獨時間花費不大於0.02秒。 計算“世界最難數獨”時間花費約為0.05秒。 計算效率中等,有待提高。 程式核心函式為place(),作用為遞迴設定下一個位置的值。
優先隊列(堆) -數據結構(C語言實現)
++ eem enter ext lock 二次 arr 快速 left 數據結構與算法分析 優先隊列 模型 Insert(插入) == Enqueue(入隊) DeleteMin(刪除最小者) == Dequeue(出隊) 基本實現 簡單鏈表:在表頭插入,並遍歷
計算1~100之間,能被3整除但是不能被7整除的數的和(C語言)
#include<stdio.h> int main(agrc *agrv) { int n,i; int sum=0; scanf("%d",&n); for(i=1;i<=n;i++){ if(i%3==0&&i%7!=0){ sum+=i; &
迴文數—簡單方法(C語言)
迴文數即正反讀都是相同的數,如151、12321等,但不要忘了,個位數與0也是迴文數,雖然這不影響我們程式碼。 題目要求:輸入n組資料,每組資料判斷是否為迴文數,是的話輸出各位數和,不是輸出no; 既然正反都是相同,許多同學用了兩個陣列進行正反比對,但我認為我的方法更為簡易。程式碼如下。
LeetCode 18. 四數之和 4Sum(C語言)
題目描述: 給定一個包含 n 個整數的陣列 nums 和一個目標值 target,判斷 nums 中是否存在四個元素 a,b,c 和 d ,使得 a + b + c + d 的值與 target 相等?找出所有滿足條件且不重複的四元組。 注意: 答案中不可以包含重複的四元組。
LeetCode 9. 迴文數 Palindrome Number(C語言)
題目描述: 判斷一個整數是否是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。 示例 1: 輸入: 121 輸出: true 示例 2: 輸入: -121 輸出: false 解釋: 從左向右讀, 為 -121 。 從右向左
LeetCode 15. 三數之和 3Sum(C語言)
題目描述: 給定一個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。 注意:答案中不可以包含重複的三元組。 例如, 給定陣列 nums = [-1, 0, 1, 2,
迴文數的判斷(C語言實現)
http://blog.sina.com.cn/s/blog_5072a15d0100msdb.html 無名小浪 https://zhidao.baidu.com/question/548255538.html zhuhuaizhong 原理: 任何一個數除以10的餘
一箇中興的面試題,輸入兩個數n和m,從數列1,2,3……n中隨意取幾個數,使其和等於m,要求將其中所有組合列出來程式設計求解(c語言遞迴函式分解法)
原題目:輸入兩個數n和m,從數列1,2,3……n中隨意取幾個數,使其和等於m,要求將其中所有組合列出來程式設計求解 c語言解法分析: 先判定n和m的大小,如果m小於n,則只需從1,2……m之間找出和為m的組合即可,如果m大於n,則需要判斷1~n的和是否
兩數之和問題(C語言解法)
給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。算例:給定 nums = [2, 7, 11, 15], target = 9
數據結構(C語言版)
info bsp cpp work spa clu 順序 9.png error 首先,學會用Vistual C++創建一個順序表,以及對順序表的基本操作。 (1)新建一個工程 Win30Application (2)新建SeqList.h (3)新建SeqList.
漢諾塔的故事(C語言——遞歸)
code log 圓盤 印度 return 16px move class baidu 漢諾塔: 漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤
資料結構---棧(C語言陣列實現)
https://blog.csdn.net/morixinguan/article/details/51374184 資料結構---棧(C語言陣列實現) 棧的全名稱為堆疊,棧其實就是與佇列相反的過程,佇列是先進先出,而棧便是先進後出了,如下圖:
資料結構---佇列(C語言陣列實現)
https://blog.csdn.net/morixinguan/article/details/51374296 資料結構---佇列(C語言陣列實現) 佇列是先進先出的過程。簡單地畫一幅畫來描述一下佇列: 一個簡單的、由陣列實現的佇列,可以由以下幾種最基本的操
二叉樹刪除前面節點(C語言初始版)
#include <stdlib.h> #include <stdio.h> typedef struct node { int key; struct node *left; struct node *right; } Btree; Btr
每日一題(C語言基礎篇)2
題目描述:使用C語言將一個整型數字轉換成字串並倒序列印,例如:123轉換成字串321,-1234轉換成字串-4321。 程式碼實現: #include <stdio.h> #include
51nod1005大數加法(C語言實現大數)
大數相加 基本思路是: 1、兩個字串把大數讀進來 然後把每一位字元換成數字存到 x y 數組裡面 2、拿 x y 陣列從後往前 對應位相加 (注意進位) 相加的結果依次存到 c數組裡 3、然後對c陣列處理 如果最高位小於0 那麼結果肯定是負數 就列印一個負
離散數學真值表(c語言程式設計實現)
程式碼如下: 廢話不多說: 主要利用二進位制的轉化實現 #include <iostream> #include <math.h> using namespace std; void shuru(char *p,int s); void shu
靜態連結串列插入和刪除操作詳解(C語言程式碼實現)
本節主要講解靜態連結串列的插入和刪除操作,有關靜態連結串列的詳細講解請閱讀《靜態連結串列及C語言實現》一文。 在講解靜態連結串列的插入和刪除操作之前,我們假設有如下的靜態連結串列: 圖中,array[0] 用作備用連結串列的頭結點,array[1] 用作存放資料的連結串列的頭結點,array[0]