1. 程式人生 > 其它 >吉林大學超星高階語言程式設計 實驗08 結構化程式設計(二)Debruijn問題(2020級)

吉林大學超星高階語言程式設計 實驗08 結構化程式設計(二)Debruijn問題(2020級)

(以下答案均由本人自己編寫,歡迎大家一起交流)
建議在完成本次實驗前對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"); } }

歡迎大家在評論區交流