1. 程式人生 > >hdu 2894 DeBruijin (歐拉回路)

hdu 2894 DeBruijin (歐拉回路)

原創部落格 :https://blog.csdn.net/a709743744/article/details/51457790

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=2894

第一問的答案毫無疑問是2^n

第二問的答案長度肯定是2^n   因為要求前n個必然是0

原問題是要求能夠表示出0-(2^n-1)的數 每個數只能出現一次 一圈是一個迴圈 每條邊也只能經過一次 就是求一個歐拉回路

從u向to1=(u<<1)&((1<<n)-1)和to2=to1+1分別連一條邊 這樣畫個圖就能看出來每個點的入度出度都是2

程式碼不是很長。

旋轉鼓的表面分成m塊扇形,如圖所示(m=8)。圖中陰影區表示用導電材料製成,空白區用絕緣材料製成,終端a、b和c是3(k=3)處接地或不是接地分別用二進位制訊號0或1表示。因此,鼓的位置可用二進位制訊號表示。試問應如何選取這8個扇形的材料使每轉過一個扇形都得到一個不同的二進位制訊號,即每轉一週,能得到000到111的8個數。


那我們現在把旋轉鼓的表面分成m塊扇形,每一份記為0或1,使得任何相繼的k個數的有序組(按同一方向)都不同,對固定的k,m最大可達到多少,並任意輸出符合條件的一個這樣的有序組。

 

 

Input

每個case輸入一個數k (2<=k<=11),表示圖中所示的abc這樣的接地線的數量。

 

 

Output

每個case輸出m所能達到的最大值 ,並且輸出字典序最小的一個符合條件的有序組,中間用空格隔開。Case間沒有空行。有序組輸出的格式為:00010111(k=3,只輸出一個週期(0001011100010111……),並且首尾剛好是相接的)。

 

 

Sample Input

 

3

 

 

Sample Output

 

8 00010111

#include<cstdio>
#include<cstring>
using namespace std;
int p, d[1 << 15], n;
bool vis[1 << 15];
void dfs(int u)
{
	int to1 = (u << 1)&((1 << n) - 1);//to1 to2就是去掉二進位制數的首位然後在末位分別加上0和1
	int to2 = to1 + 1;//也就是模擬在k個接地部分旋轉的情況 旋轉一格 首位消失 添上末位 末位是0或者是1
	if (!vis[to1])//因為不能重複出現所以要進行vis標記
	{
		vis[to1] = true;
		dfs(to1);
		d[++p] = 0;
	}
	if (!vis[to2])//先搜0的之前的0無法達成的話 在搜1 這樣就能實現字典序最小
	{//因為是dfs的關係 所以採用棧結構(等下逆序輸出)
		vis[to2] = true;
		dfs(to2);
		d[++p] = 1;
	}
}
int main()
{
	//freopen("C://input.txt", "r", stdin);
	while (scanf("%d", &n) != EOF)
	{
		memset(vis, 0, sizeof(vis));
		p = 0;
		dfs(0);//深搜
		printf("%d ", 1 << n);
		//printf("%d\n", p);
		for (int i = 1; i < n; i++) printf("0");//輸出前導0
		for (int i = p; i >= n; i--) printf("%d", d[i]);//逆序輸出棧中的數
		printf("\n");
	}
	return 0;
}