當前位置:首頁 » 操作系統 » puzzle演算法

puzzle演算法

發布時間: 2022-08-18 15:24:30

⑴ 3*3 型的拼圖界面。數字1~8 和一個空格。要實現能拼圖功能~~大概的演算法是怎樣的!!

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<time.h>

int main(void)
{
void swap(int *a,int *b); //子函數聲明
int i,j,k,n,puzzle[81]={0},parity[81]={0}; //拼圖數組和奇偶性數組
char ch; //用來記錄拼圖數組可以轉換成順序矩陣,還是逆序矩陣

printf("游戲說明\n");
printf("↑ :數字向上 ↓ :數字向下\n");
printf("← :數字向左 → :數字向右\n");
printf("Esc:退出程序 Space:重置矩陣\n");
printf("\n");
loop1:
printf("難度設置\nn:");
scanf("%d",&n);
loop2:
system("cls"); //清屏
srand((unsigned)time(NULL)); //動態獲取數據
for(i=0;i<=n*n-1;i++)
{
loop3:
k=rand()%(n*n); //記錄新的數據
for(j=0;j<i;j++) //和舊的數據進行比較,當新的數據
if(puzzle[j]==k) goto loop3; //出現過時,重新獲取
if(j==i)
{
puzzle[j]=k; //當新的數據和舊的數據都不同時,將
} //數據放入拼圖數組中
}
for(i=0;i<=n*n-1;i++)
{
parity[i]=puzzle[i]; //將拼圖數組賦予奇偶性數組
}
for(i=0;i<=n*n-1;i++)
{
if(parity[i]==0) break; //找出奇偶性數組中0(空格)的位置
}
k=i;
for(j=1;j<=i/n;j++) //將0(空格)換到第1行
{
swap(&parity[k],&parity[k-n]);
k=k-n; //更新奇偶性數組中0(空格)的位置
}
for(j=1;j<=i%n;j++) //將0(空格)換到第1列
{
swap(&parity[k],&parity[k-1]);
k=k-1; //更新奇偶性數組中0(空格)的位置
}
k=0;
for(i=0;i<=n*n-1;i++)
for(j=i;j<=n*n-1;j++)
{
if(parity[i]>parity[j]) k++; //求奇偶性數組的「逆序數和」
}
if(k%2==0) printf("%d\n順序矩陣",n),ch='0'; //「逆序數和」為偶數時,是順序矩陣
else printf("%d\n逆序矩陣",n),ch='1'; //「逆序數和」為奇數時,是逆序矩陣
printf("\n");
for(i=0;i<=n*n-1;i++) //列印拼圖數組
{
if(puzzle[i]==0) printf("%*c",n,' '); //是0(空格)的位置,列印空格
else printf("%-*d",n,puzzle[i]); //是數字的位置,列印對應寬度的數字
if((i+1)%n==0&&i!=n*n-1) printf("\n"); //每列印n個數字,換一行列印
}
while(1)
{
for(i=0;i<=n*n-1;i++)
{
if(puzzle[i]==0) break; //記錄拼圖數組中0(空格)的位置
}
switch(getch())
{
case 72:if( i<n*(n-1)) swap(&puzzle[i],&puzzle[i+n]);break; //數字向上
case 80:if( i>1*(n-1)) swap(&puzzle[i],&puzzle[i-n]);break; //數字向下
case 75:if((i+1)%n!=0) swap(&puzzle[i],&puzzle[i+1]);break; //數字向左
case 77:if((i+0)%n!=0) swap(&puzzle[i],&puzzle[i-1]);break; //數字向右
case 27:exit(0); //退出程序
case 32:goto loop2; //重置矩陣
}
system("cls"); //清屏
switch(ch)
{
case '0':printf("%d\n順序矩陣\n",n);break; //完成拼圖的最終目標
case '1':printf("%d\n逆序矩陣\n",n);break; //完成拼圖的最終目標
}
for(i=0;i<=n*n-1;i++)
{
if(puzzle[i]==0) printf("%*c",n,' '); //是0(空格)的位置,列印空格
else printf("%-*d",n,puzzle[i]); //是數字的位置,列印對應寬度的數字
if((i+1)%n==0&&i!=n*n-1) printf("\n"); //每列印n個數字,換一行列印
}
for(i=0;i<=n*n-3;i++)
{
if(puzzle[i]!=i) break; //判斷拼圖數組是否為順序矩陣或逆序矩陣
}
if(i==n*n-2)
{ //是順序矩陣或是逆序矩陣時,完成拼圖
printf("\n恭喜你,拼圖完成了!\n"); //列印完成標志
printf("Continue(y/n)?");
if(getch()=='y')
{
system("cls"); //清屏
goto loop1; //重新開始
}
else
{
exit(0); //退出程序
}
}
}
getch(); //顯示運行結果
return(0); //正常運行返回0
}

void swap(int *a,int *b)
{
int c;

c=*a;
*a=*b;
*b=c;
}

⑵ 誰有用A* search/演算法 解16puzzle/8puzzle/25puzzle 的詳細演算法或者代碼

首先是規則,其次是模擬運行,校驗。最後是優化。

我看優化的要點是優先檢驗小數字是否還需移動。可以把已經一動完成的小塊鎖住,這樣就可以排除大量沒用的移動。

⑶ 啟發式演算法的新演算法

如何找到一個分叉率較少又通用的合理啟發式演算法,已被人工智慧社群深入探究過。 他們使用幾種常見技術:
部分問題的解答的代價通常可以評估解決整個問題的代價,通常很合理。例如一個10-puzzle拼盤,解題的代價應該與將1到5的方塊移回正確位置的代價差不多。通常解題者會先建立一個儲存部份問題所需代價的模式資料庫(pattern database)以評估問題。 解決較易的近似問題通常可以拿來合理評估原先問題。例如曼哈頓距離是一個簡單版本的n-puzzle問題,因為我們假設可以獨立移動一個方塊到我們想要的位置,而暫不考慮會移到其他方塊的問題。 給我們一群合理的啟發式函式h1(n),h2(n),...,hi(n),而函式h(n) = max{h1(n),h2(n),...,hi(n)}則是個可預測這些函式的啟發式函式。 一個在1993年由A.E. Prieditis寫出的程式ABSOLVER就運用了這些技術,這程式可以自動為問題產生啟發式演算法。ABSOLVER為8-puzzle產生的啟發式演算法優於任何先前存在的!而且它也發現了第一個有用的解魔術方塊的啟發式程式。

⑷ 誰來看下我的迷宮演算法(還沒做完)為啥就空指針了

我來給你分析一下,首先你在RunPuzzle里通過main方法來啟動整個程序。在main方法中,首先定義了一個字元串數組,然後通過這個字元串數組來創建一個puzzle,下面我們到puzzle的構造方法里看看你是怎麼創建這個puzzle的,首先呢,你創建了一個9*9的Lattice二維數組L,注意你這個時候並沒有對這個數組L里的每一個元素賦值為某個真正的Lattice對象的引用,說的更明確一點,現在這個二維數組里全部都是null,所以接下來你的代碼在二重循環里便直接用「L[i][j].setPos(i, j);」來調用setPos當然會出現空指針異常了,因為這時L[i][j]全部都是null,明白了么?
請樓主給我加分吧,哈哈

⑸ 啟發式演算法的最短路徑

所謂的最短路徑問題有很多種意思, 在這里啟發式指的是一個在一個搜尋樹的節點上定義的函數h(n),用於評估從此節點到目標節點最便宜的路徑。啟發式通常用於資訊充分的搜尋演算法,例如最好優先貪婪演算法與A*。最好優先貪婪演算法會為啟發式函數選擇最低代價的節點;A*則會為g(n) + h(n)選擇最低代價的節點,此g(n)是從起始節點到目前節點的路徑的確實代價。如果h(n)是可接受的(admissible)意即h(n)未曾付出超過達到目標的代價,則A*一定會找出最佳解。
最能感受到啟發式演算法好處的經典問題是n-puzzle。此問題在計算錯誤的拼圖圖形,與計算任兩塊拼圖的曼哈頓距離的總和以及它距離目的有多遠時,使用了本演算法。注意,上述兩條件都必須在可接受的范圍內。

⑹ C++編程,用A*演算法重排九宮圖(eight-puzzle)

POJ 有原題

⑺ tree-puzzle

序列比對建議用ClustalX
建NJ或MP樹,用MEGA就可以了,非常方便
若要建ML樹推薦用phyML
建Bayes樹推薦用Parallel MrBayes @ BioHPC

如果不是專業建樹的話,MEGA足夠用了,建議參考下面這篇文章:

一、引言
開始動筆寫這篇短文之前,我問自己,為什麼要寫這樣的文章?寫這樣的文章有實際的意義嗎?我希望能夠解決什麼樣的問題?帶著這樣的疑惑,我隨手在丁香園(DXY)上以關鍵字「進化 分析 求助」進行了搜索,居然有289篇相關的帖子(2006年9月12日)。而以關鍵字「進化分析」和「進化」為關鍵字搜索,分別找到2,733和7,724篇相關的帖子。考慮到有些帖子的內容與分子進化無關,這里我保守的估計,大約有 3,000~4,000篇帖子的內容,是關於分子進化的。粗略地歸納一下,我大致將提出的問題分為下述的幾類:

1.涉及基本概念
例如,「分子進化與生物進化是不是一個概念」,「關於微衛星進化模型有沒有什麼新的進展」以及「關於Kruglyak的模型有沒有改進的出現」,等等。

2.關於構建進化樹的方法的選擇
例如,「用boostrap NJ得到XX圖,請問該怎樣理解?能否應用於文章?用boostrap test中的ME法得到的是XXX樹,請問與上個樹比,哪個更好」,等等。

3.關於軟體的選擇
例如,「想做一個進化樹,不知道什麼軟體能更好的使用且可以說明問題,並且有沒有說明如何做」,「拿到了16sr RNA數據,打算做一個系統進化樹分析,可是原來沒有做過這方面的工作啊,都要什麼軟體」,「請問各位高手用ClustalX做出來的進化樹與 phylip做的有什麼區別」,「請問有做過進化樹分析的朋友,能不能提供一下,做樹的時候參數的設置,以及代表的意思。還有各個分支等數值的意思,說明的問題等」,等等。

4.蛋白家族的分類問題
例如,「搜集所有的關於一個特定domain的序列,共141條,做的進化樹不知具體怎麼分析」,等等。

5.新基因功能的推斷
例如,「根據一個新基因A氨基酸序列構建的系統發生樹,這個進化樹能否說明這個新基因A和B同源,屬於同一基因家族」,等等。

6.計算基因分化的年代
例如,「想在基因組水平比較兩個或三個比較接近物種之間的進化年代的遠近,具體推算出他們之間的分歧時間」,「如何估計病毒進化中變異所需時間」,等等。

7.進化樹的編輯
例如生成的進化樹圖片,如何進行後續的編輯,比如希望在圖片上標注某些特定的內容,等等。

由於相關的帖子太多,作者在這里對無法閱讀全部的相關內容而致以歉意。同時,作者歸納的這七個問題也並不完全代表所有的提問。對於問題1所涉及到的基本的概念,作者推薦讀者可參考由Masatoshi Nei與Sudhir Kumar所撰寫的《分子進化與系統發育》(Molecular Evolution and Phylogenetics)一書,以及相關的分子進化方面的最新文獻。對於問題7,作者之一lylover一般使用Powerpoint進行編輯,而 Photoshop、Illustrator及Windows自帶的畫圖工具等都可以使用。

這里,作者在這里對問題2-6進行簡要地解釋和討論,並希望能夠初步地解答初學者的一些疑問。

二、方法的選擇
首先是方法的選擇。基於距離的方法有UPGMA、ME(Minimum Evolution,最小進化法)和NJ(Neighbor-Joining,鄰接法)等。其他的幾種方法包括MP(Maximum parsimony,最大簡約法)、ML(Maximum likelihood,最大似然法)以及貝葉斯(Bayesian)推斷等方法。其中UPGMA法已經較少使用。

一般來講,如果模型合適,ML的效果較好。對近緣序列,有人喜歡MP,因為用的假設最少。MP一般不用在遠緣序列上,這時一般用NJ或ML。對相似度很低的序列,NJ往往出現Long-branch attraction(LBA,長枝吸引現象),有時嚴重干擾進化樹的構建。貝葉斯的方法則太慢。對於各種方法構建分子進化樹的准確性,一篇綜述(Hall BG. Mol Biol Evol 2005, 22(3):792-802)認為貝葉斯的方法最好,其次是ML,然後是MP。其實如果序列的相似性較高,各種方法都會得到不錯的結果,模型間的差別也不大。

對於NJ和ML,是需要選擇模型的。對於各種模型之間的理論上的區別,這里不作深入的探討,可以參看Nei的書。對於蛋白質序列以及DNA序列,兩者模型的選擇是不同的。以作者的經驗來說,對於蛋白質的序列,一般選擇Poisson Correction(泊松修正)這一模型。而對於核酸序列,一般選擇Kimura 2-parameter(Kimura-2參數)模型。如果對各種模型的理解並不深入,作者並不推薦初學者使用其他復雜的模型。

Bootstrap幾乎是一個必須的選項。一般Bootstrap的值>70,則認為構建的進化樹較為可靠。如果Bootstrap的值太低,則有可能進化樹的拓撲結構有錯誤,進化樹是不可靠的。

對於進化樹的構建,如果對理論的了解並不深入,作者推薦使用預設的參數。需要選擇模型的時候(例如用NJ或者ML建樹),對於蛋白序列使用Poisson Correction模型,對於核酸序列使用Kimura-2參數模型。另外需要做Bootstrap檢驗,當Bootstrap值過低時,所構建的進化樹其拓撲結構可能存在問題。並且,一般推薦用兩種不同的方法構建進化樹,如果所得到的進化樹類似,則結果較為可靠。

三、軟體的選擇
表1中列出了一些與構建分子進化樹相關的軟體。

構建NJ樹,可以用PHYLIP(寫得有點問題,例如比較慢,並且Bootstrap檢驗不方便)或者MEGA。MEGA是Nei開發的方法並設計的圖形化的軟體,使用非常方便。作者推薦MEGA軟體為初學者的首選。雖然多雪列比對工具ClustalW/X自帶了一個NJ的建樹程序,但是該程序只有p- distance模型,而且構建的樹不夠准確,一般不用來構建進化樹。

構建MP樹,最好的工具是PAUP,但該程序屬於商業軟體,並不對學術免費。因此,作者並不建議使用PAUP。而MEGA和PHYLIP也可以用來構建進化樹。這里,作者推薦使用MEGA來構建MP樹。理由是,MEGA是圖形化的軟體,使用方便,而PHYLIP則是命令行格式的軟體,使用較為繁瑣。對於近緣序列的進化樹構建,MP方法幾乎是最好的。

構建ML樹可以使用PHYML,速度最快。或者使用Tree-puzzle,速度也較快,並且該程序做蛋白質序列的進化樹效果比較好。而PAML則並不適合構建進化樹。ML的模型選擇是看構出的樹的likelihood值,從參數少,簡單的模型試起,到likelihood值最大為止。ML也可以使用 PAUP或者PHYLIP來構建。這里作者推薦的工具是BioEdit。BioEdit集成了一些PHYLIP的程序,用來構建進化樹。Tree- puzzle是另外一個不錯的選擇,不過該程序是命令行格式的,需要學習DOS命令。PHYML的不足之處是沒有win32的版本,只有適用於64位的版本,因此不推薦使用。值得注意的是,構建ML樹,不需要事先的多序列比對,而直接使用FASTA格式的序列即可。

貝葉斯的演算法以MrBayes為代表,不過速度較慢。一般的進化樹分析中較少應用。由於該方法需要很多背景的知識,這里不作介紹。

表1 構建分子進化樹相關的軟體

軟體 網址 說明
ClustalX 圖形化的多序列比對工具
ClustalW 命令行格式的多序列比對工具
GeneDoc 多序列比對結果的美化工具(可以導入fasta格式的文件,出來的圖可用於發表,我用過)
BioEdit 序列分析的綜合工具
MEGA 圖形化、集成的進化分析工具,不包括ML
PAUP 商業軟體,集成的進化分析工具
PHYLIP 免費的、集成的進化分析工具
PHYML 最快的ML建樹工具
PAML ML建樹工具
Tree-puzzle 較快的ML建樹工具
MrBayes 基於貝葉斯方法的建樹工具
MAC5 基於貝葉斯方法的建樹工具
TreeView 進化樹顯示工具
(加紅色標注的為最通用的分析軟體)

需要注意的幾個問題是,其一,如果對核酸序列進行分析,並且是CDS編碼區的核酸序列,一般需要將核酸序列分別先翻譯成氨基酸序列,進行比對,然後再對應到核酸序列上。這一流程可以通過MEGA 3.0以後的版本實現。MEGA3現在允許兩條核苷酸,先翻成蛋白序列比對之後再倒回去,做後續計算。

其二,無論是核酸序列還是蛋白序列,一般應當先做成 FASTA格式。FASTA格式的序列,第一行由符號「>」開頭,後面跟著序列的名稱,可以自定義,例如user1,protein1等等。將所有的FASTA格式的序列存放在同一個文件中。文件的編輯可用Windows自帶的記事本工具,或者EditPlus(google搜索可得)來操作。

另外,構建NJ或者MP樹需要先將序列做多序列比對的處理。作者推薦使用ClustalX進行多序列比對的分析。多序列比對的結果有時需要後續處理並應用於文章中,這里作者推薦使用GeneDoc工具。而構建ML樹則不需要預先的多序列比對。
因此,作者推薦的軟體組合為:MEGA + ClustalX + GeneDoc + BioEdit。

四、數據分析及結果推斷
一般碰到的幾類問題是,(1)推斷基因/蛋白的功能;(2)基因/蛋白家族分類;(3)計算基因分化的年代。關於這方面的文獻非常多,這里作者僅做簡要的介紹。

推斷基因/蛋白的功能,一般先用Blast工具搜索同一物種中與不同物種的同源序列,這包括直向同源物(ortholog)和旁系同源物(paralog)。如何界定這兩種同源物,網上有很多詳細的介紹,這里不作討論。然後得到這些同源物的序列,做成FASTA格式的文件。一般通過NJ構建進化樹,並且進行Bootstrap分析所得到的結果已足夠。如果序列近緣,可以再使用MP構建進化樹,進行比較。如果序列較遠源,則可以做ML樹比較。使用兩種方法得到的樹,如果差別不大,並且Bootstrap總體較高,則得到的進化樹較為可靠。

基因/蛋白家族分類。這方面可以細分為兩個問題。一是對一個大的家族進行分類,另一個就是將特定的一個或多個基因/蛋白定位到已知的大的家族上,看看屬於哪個亞家族。例如,對驅動蛋白(kinesin)超家族進行分類,屬於第一個問題。而假如得到一個新的驅動蛋白的序列,想分析該序列究竟屬於驅動蛋白超家族的14個亞家族中的哪一個,則屬於後一個問題。這里,一般不推薦使用MP的方法。大多數的基因/蛋白家族起源較早,序列分化程度較大,相互之間較為遠源。這里一般使用NJ、ME或者ML的方法。

計算基因分化的年代。這個一般需要知道物種的核苷酸替代率。常見物種的核苷酸替代率需要查找相關的文獻。這里不作過多的介紹。一般對於這樣的問題,序列多數是近緣的,選擇NJ或者MP即可。
如果使用MEGA進行分析,選項中有一項是「Gaps/Missing Data」,一般選擇「Pairwise Deletion」。其他多數的選項保持預設的參數。

五、總結
在實用中,只要方法、模型合理,建出的樹都有意義,可以任意選擇自己認為好一個。最重要的問題是:你需要解決什麼樣的問題?如果分析的結果能夠解決你現有的問題,那麼,這樣的分析足夠了。因此,在做進化分析前,可能需要很好的考慮一下自己的問題所在,這樣所作的分析才有針對性。

六、致謝

本文由mediocrebeing在2005年9月8日所發起的討論《關於建樹的經驗》擴充、修改而來。文章的作者按原貼ID出現先後排名,由 lylover執筆。作者同時感謝所有參與討論的戰友。作者lylover感謝中國科大細胞動力學實驗室的金長江博士所給的一些有益的建議。

來源:丁香園(mediocrebeing, rodger, lylover , klaus, oldfish, yzwpf)

⑻ 撲克24演算法

我有兩種,一種是隨機搜索法,一種是用排列組合的方法窮舉:第二種寫的時候復雜了一點,呵呵:下面程序有兩種方法,你看看互相的調用吧。/* Calcu24.cpp : Defines the entry point for the console application.
weizengke
2010-6-6 隨機解法
2010-10-7 全局搜索法
*/#include "stdafx.h"
#include "conio.h"
#include "stdlib.h"
#include "time.h"
#include "math.h"
#include "string.h"
#include "iostream.h"
/*
從一副撲克牌中,任取4張。
2-10 按其點數計算(為了表示方便10用T表示),J,Q,K,A 統一按 1 計算
要求通過加減乘除四則運算得到數字 24。
本程序可以隨機抽取紙牌,並用試探法求解。
*/
int s[21][4]={-1};
int sum=0;
void GivePuzzle(char* buf)
{
char card[] = {'A','2','3','4','5','6','7','8','9','T','J','Q','K'};
for(int i=0; i<4; i++){
buf[i] = card[rand() % 13];
}
}void SetPuzzle(char *buf)
{
scanf("%c %c %c %c",&buf[0],&buf[1],&buf[2],&buf[3]);
}
void shuffle(char * buf)
{
for(int i=0; i<5; i++){
int k = rand() % 4;
char t = buf[k];
buf[k] = buf[0];
buf[0] = t;
}
}
int GetCardValue(int c)
{
if(c=='T') return 10;
if(c>='0' && c<='9') return c - '0';
return 1;
}
char GetOper(int n)
{
switch(n)
{
case 0:
return '+';
case 1:
return '-';
case 2:
return '*';
case 3:
return '/';
} return ' ';
}double MyCalcu(double op1, double op2, int oper)
{
switch(oper)
{
case 0:
return op1 + op2;
case 1:
return op1 - op2;
case 2:
return op1 * op2;
case 3:
if(fabs(op2)>0.0001)
return op1 / op2;
else
return 100000;
} return 0;
}
void MakeAnswer(char* answer, int type, char* question, int* oper)
{
char p[4][3];
for(int i=0; i<4; i++)
{
if( question[i] == 'T' )
strcpy(p[i], "10");
else
sprintf(p[i], "%c", question[i]);
}

switch(type)
{
case 0:
sprintf(answer, "%s %c (%s %c (%s %c %s))",
p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);
break;
case 1:
sprintf(answer, "%s %c ((%s %c %s) %c %s)",
p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);
break;
case 2:
sprintf(answer, "(%s %c %s) %c (%s %c %s)",
p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);
break;
case 3:
sprintf(answer, "((%s %c %s) %c %s) %c %s",
p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);
break;
case 4:
sprintf(answer, "(%s %c (%s %c %s)) %c %s",
p[0], GetOper(oper[0]), p[1], GetOper(oper[1]), p[2], GetOper(oper[2]), p[3]);
break;
}
}
bool TestResolve(char* question, int* oper, char* answer)
{
// 等待考生完成
int type[5]={0,1,2,3,4};//計算類型
double p[4];
double sum=0;

for(int i=0; i<4; i++) //循環取得點數
{
p[i]=GetCardValue(int(question[i]));
} for(i=0;i<5;i++)
{
MakeAnswer(answer,type[i],question,oper); //獲取可能的答案
//printf("Doing:%s\n", answer);
switch(type[i])
{
case 0:
sum=MyCalcu(p[0],MyCalcu( p[1],MyCalcu(p[2], p[3], oper[2]),oper[1]),oper[0]); //A*(B*(c*D))
break;
case 1:
sum=MyCalcu(p[0],MyCalcu(MyCalcu(p[1], p[2], oper[1]),p[3],oper[2]),oper[0]); //A*((B*C)*D)
break;
case 2:
sum=MyCalcu(MyCalcu(p[0], p[1], oper[0]),MyCalcu(p[2], p[3], oper[2]),oper[1]); // (A*B)*(C*D)
break;
case 3:
sum=MyCalcu(MyCalcu(MyCalcu(p[0], p[1], oper[0]),p[2],oper[1]),p[3],oper[2]); //((A*B)*C)*D
break;
case 4:
sum=MyCalcu(MyCalcu(p[0],MyCalcu(p[1], p[2], oper[1]),oper[0]),p[3],oper[2]); //(A*(B*C))*D
break;
}
if(sum==24) return true;
}
return false;
}
bool permNum(int* oper, int i,int N,char*question,char*answer) //遞歸實現重新排列數字、運算符
{
int j, k;
char tmp;
if(i < N)
{
for(j = i; j < N; j++)
{
tmp = question[j];
for(k = j; k > i; k--)
question[k] = question[k-1];
question[i] = tmp;
if( permNum(oper, i+1,N,question,answer)) return true;
for(k = i; k < j; k++)
question[k] = question[k+1];
question[j] = tmp;
}
}
else
{
//int type;
if( TestResolve(question, oper, answer) )
{
//getch();
return true;
}
}
return false;
}
bool perm(int* num, int i,int N,char*question,char*answer) //遞歸實現重新排列數字、運算符
{
int j, k, tmp;
if(i < N)
{
for(j = i; j < N; j++)
{
tmp = num[j];
for(k = j; k > i; k--)
num[k] = num[k-1];
num[i] = tmp;
if(perm(num, i+1,N,question,answer)) return true;
for(k = i; k < j; k++)
num[k] = num[k+1];
num[j] = tmp;
}
}
else
{
if (permNum(num,0,4,question,answer)) return true;
}
return false;
}
int ifcan(int str[4])
{
for(int i=0;i<sum;i++)
{
if(s[i][0]==str[0]&&s[i][1]==str[1]&&s[i][2]==str[2]) {

return 1;
}
}
s[i-1][0]=str[0];
s[i-1][1]=str[1];
s[i-1][2]=str[2];
sum++;
return 0;
}bool Chooseoper(int *oper,char*question,char*answer) //遞歸從四個運算符獲取三個運算符
{

int n=3,m=12,i,j;
int oper1[12];

for (i=0;i<n;i++)
{
oper1[i]=i;
}

for (i=0;i<n;i++)
{
oper[i]=oper1[i]/3;
}

if (!ifcan(oper))
{
if(perm(oper,0,n,question,answer)) return true;
}

j=n-1;
while (1)
{
if (oper1[n-1]==m-1)
j--;
else j=n-1;
oper1[j]++;
for (i=j+1;i<n;i++)
oper1[i]=oper1[i-1]+1;

for (i=0;i<n;i++)
{
oper[i]=oper1[i]/3;
}
if (!ifcan(oper))
{
if(perm(oper,0,n,question,answer)) return true;
}

if (oper1[0]>=m-n)
break;
}
return false;
}
bool Try(int *oper,char*question,char* answer)
{
if(Chooseoper(oper,question,answer)) return true;
return false;
}
int main(int argc, char* argv[])
{
// 初始化隨機種子
srand( (unsigned)time( NULL ) );
char buf1[4]; // 題目
char buf2[30]; // 解答

printf("***************************\n");
printf("計算24\n");
printf("A J Q K 均按1計算,其它按牌點計算,T 代表 10\n");
printf("目標是:通過四則運算組合出結果:24\n");
printf("Mode 1 of Give Puzzle: Rand to give puzzle\n");
printf("Else Type of Give Puzzle:Give by Youself \n");
printf("***************************\n\n");
int mode=1; //默認為1
printf("Mode:");
scanf("%d",&mode);
getchar();
printf("***************************\n");
for(;;)
{

if (mode==1)
{
GivePuzzle(buf1); // 出題模式1
}
else
{
printf("Num:");
SetPuzzle(buf1); //出題模式2
}
getchar();
printf("題目:");
for(int j=0; j<4; j++){
if( buf1[j] == 'T' )
printf("10 ");
else
printf("%c ", buf1[j]);
} printf("\n按任意鍵參考答案...\n");
getch(); int type[4];
if( Try(type, buf1,buf2) ) //1全局搜索解法,精確解
printf("參考:%s\n", buf2);
else
printf("無解...\n"); for (int i=0;i<sum;i++)
{
for(int j=0;j<3;j++)
s[i][j]=-1;
}
sum=0; printf("按任意鍵出下一題目,x 鍵退出...\n");
if( getch() == 'x' ) break; } return 0;
}

⑼ 數獨演算法

給你數獨計算器:
http://blog.xunlei.com/web/category.html?uin=mianmiany1978&category_id=143
數獨游戲:
http://blog.xunlei.com/web/category.html?uin=mianmiany1978&category_id=174
數獨演算法:
http://www.puzzle8.com/suku/news.asp
數獨快速入門(上篇)
數獨快速入門(中篇)
數獨快速入門(下篇)
唯一解法
唯一候選數法
隱性三鏈數刪減法
隱性數對刪減法
三鏈列刪減法
區塊刪減法
矩形頂點刪減法
關鍵數刪減法

補充:
合格的數獨是只有唯一解。
而數獨有難易度的分類,找一份報紙注意刊登的數獨謎題是1星,還是5星。
在網路上,更分成容易題、進階題、難題、極難題、超難題....
一般都是依據需要運用的技巧,而技巧是區分難易的。

數獨不用猜測,解題全部是運用邏輯推理。
數獨不用電腦程序分析,就可以解的題目是直觀法數獨題。
而超難題是需要電腦分析,及把全盤標示可選數,那是可選數謎題。
沒有所謂解題通則。

1.直觀解(一般報紙、書籍)
直觀法技巧
直觀法技巧 01 (容易級) 唯一解
直觀法技巧 02 (容易級) 基本摒除
直觀法技巧 03 (進階級) 宮對行列摒除
直觀法技巧 04 (進階級) 行列對宮摒除
直觀法技巧 05 (進階級) 群組解法
直觀法技巧 06 (困難級) X-Wing摒除法01
直觀法技巧 06 (困難級) X-Wing摒除法02
直觀法技巧 07 (困難級) 數偶摒除法

http://hi..com/kiwy07/blog/item/181fc482a153f3bd6c8119ab.html

2.可選數(以程序自動生成可選數)

Last value in block, row or column
Hidden Single in block
Hidden Single in row or column
Direct Pointing
Direct Claiming
Direct Hidden Pair
Naked Single
Direct Hidden Triplet
Pointing
Claiming
Naked Pair, X-Wing, Hidden Pair
Naked Triplet, Swordfish, Hidden Triplet
XY-Wing, XYZ-Wing
Unique rectangles and loops
Naked Quad, Jellyfish, Hidden Quad
Bivalue Universal Graves
Aligned Pair Exclusion
Bidirectioal X-Cycles and Y-Cycles
Forcing X-Chains
Forcing Chains, Bidirectional Cycles
Nishio
Cell/Region Forcing Chains
Dynamic Forcing Chains

http://diuf.unifr.ch/people/juillera/Sudoku/FAQ.html

通則無法解的題
直觀難題
006589307
030602008
809703500
000891403
394265871
180374000
003026785
000458030
008037200
可選數極難題
970000000
003927000
008410709
300700400
060050070
007040003
105074900
000068507
786000042
不要把謎題解一次列出,而是找出下一步,及他的邏輯推理方法。
不要用猜測。

⑽ "最短路徑優先演算法"的優缺點

所謂的最短路徑問題有很多種意思,
在這里啟發式指的是一個在一個搜尋樹的節點上定義的函數h(n),用於評估從此節點到目標節點最便宜的路徑。啟發式通常用於資訊充分的搜尋演算法,例如最好優先貪婪演算法與a*。最好優先貪婪演算法會為啟發式函數選擇最低代價的節點;a*則會為g(n)
+
h(n)選擇最低代價的節點,此g(n)是從起始節點到目前節點的路徑的確實代價。如果h(n)是可接受的(admissible)意即h(n)未曾付出超過達到目標的代價,則a*一定會找出最佳解。
最能感受到啟發式演算法好處的經典問題是n-puzzle。此問題在計算錯誤的拼圖圖形,與計算任兩塊拼圖的曼哈頓距離的總和以及它距離目的有多遠時,使用了本演算法。注意,上述兩條件都必須在可接受的范圍內。

熱點內容
蒙皮演算法 發布:2025-01-18 12:57:53 瀏覽:549
常用的r語言編譯器 發布:2025-01-18 12:55:05 瀏覽:199
同人志解壓密碼 發布:2025-01-18 12:55:05 瀏覽:876
qq密碼不記得怎麼辦 發布:2025-01-18 12:48:22 瀏覽:448
安卓系統停用怎麼辦 發布:2025-01-18 12:35:49 瀏覽:260
五菱宏光星辰哪個配置最值得買 發布:2025-01-18 12:29:43 瀏覽:595
鴻蒙系統為什麼完美兼容安卓應用 發布:2025-01-18 12:16:02 瀏覽:856
數分轉演算法 發布:2025-01-18 12:08:31 瀏覽:612
iphone硬體為什麼比安卓更好 發布:2025-01-18 12:08:29 瀏覽:822
醫院冷熱源配置有哪些 發布:2025-01-18 12:08:26 瀏覽:167