吉林大學超星高階語言程式設計 實驗08 結構化程式設計(二)Debruijn問題(2020級)
阿新 • • 發佈:2021-01-04
(以下答案均由本人自己編寫,歡迎大家一起交流)
建議在完成本次實驗前對DFS演算法有一定了解。
題目編號:Exp08-Enhance02,GJBook3-12-17
題目名稱:Debruijn問題
題目描述:
如圖所示由2^3 個二進位制數字0和1組成一個環。使 2^3 個 3 位的二進位制數正好在環中各出現一次。圖中目前所示順序是:0、1、2、5、3、7、6、4。設計生成這樣環的程式,環由 2^n 個二進位制數字組成,恰好包含 2^n 個互不相同的n位二進位制數。
輸入:n(n<=4)
輸出:按照字典序輸出符合的答案(當出現多組本質不同的解時,僅輸出字典序中最小的那個序列);每行數字間以一個西文空格間隔,行末有一個換行符。
樣例1:
輸入:
3
輸出:
0 0 0 1 0 1 1 1
思路:
這裡我們仍採用dfs演算法。
我的思路是先生成所有的n位二進位制數,以n=3舉例有000,001,010,011,100,101,110,111.我們從頭開始排這些二進位制數,顯然,由於輸出的是字典序中最小的那個序列,所以開頭我們可以先填入000,然後在剩下的數中尋找前兩項是00的二進位制數,如001,那我們將1填入序列。再尋找開頭為01的二進位制數,如010,011,
以上是遞迴思路
以下是遞迴出口的設定
仍以n=3舉例,當我們填入了7個數時,我們已經把二進位制數填完了(000開頭就已被填入,所以只需填剩下的七個數)但這時候序列中有十個數,因為要構成環,所以結尾的兩個數要與開頭的兩個數相同,如若相同,則滿足提議,我們就找出了一個Debruijn序列。
#include<stdio.h>
int a[20][5],n,b[5],p=0,d[200],book[20]={0}/*用來標記數是否被使用過*/,e[200][200],p1=0;
int cmp(int t,int w);//判斷該數的前n-1項是否與序列的後n-1項相同
void dfs(int w){
int j,i;
if(w==p){//遞迴出口
for(j=0;j<n;j++){
if(d[j]!=d[j+p])return;
}
for(j=0;j<p;j++){
e[p1][j]=d[j];//將滿足條件的序列填入e中
}
p1++;
return ;
}
for(i=0;i<p;i++){
if(book[i]==0&&cmp(i,w)){
d[w+n-1]=a[i][n-1];
book[i]=1;//標記該數已使用
dfs(w+1);//走一步
book[i]=0;//這是最重要的一步!一定要將嘗試的數收回,才能嘗試下一步
}
}
}
int cmp(int t,int w){
int i;
for(i=0;i<n-1;i++){
if(a[t][i]!=d[w+i])return 0;
}
return 1;
}
void put(void){
int i;
for(i=0;i<n;i++){
a[p][i]=b[i];//將生成的二進位制數填入a中
}
p++;
}
void exh(int m){//生成二進位制數
int i;
if(m==n){
put();
}
else if(m<n){
for(i=0;i<=1;i++){
b[m]=i;
exh(m+1);
}
}
}
int main(void){
int i;
scanf("%d",&n);
for(i=0;i<n;i++){
d[i]=0;
}
book[0]=1;
exh(0);
dfs(1);
for(int j=0;j<p;j++){
printf("%d",e[0][j]);//e中的第一個序列就是字典序最小的序列
if(j!=p-1){
printf(" ");
}
else printf("\n");
}
}
歡迎大家在評論區交流