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; }