1. 程式人生 > >BZOJ3033: 太鼓達人(歐拉回路)

BZOJ3033: 太鼓達人(歐拉回路)

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 524  Solved: 400
[Submit][Status][Discuss]

Description

  七夕祭上,Vani牽著cl的手,在明亮的燈光和歡樂的氣氛中愉快地穿行。這時,在前面忽然出現了一臺太鼓達人機臺,而在機臺前坐著的是剛剛被精英隊伍成員XLk、Poet_shy和lydrainbowcat拯救出來的的applepi。看到兩人對太鼓達人產生了興趣,applepi果斷閃人,於是cl拿起鼓棒準備挑戰。然而即使是在普通難度下,cl的路人本性也充分地暴露了出來。一曲終了,不但沒有過關,就連鼓都不靈了。Vani十分過意不去,決定幫助工作人員修鼓。

  鼓的主要元件是M個圍成一圈的感測器。每個感測器都有開和關兩種工作狀態,分別用1和0表示。顯然,從不同的位置出發沿順時針方向連續檢查K個感測器可以得到M個長度為K的01串。Vani知道這M個01串應該是互不相同的。而且鼓的設計很精密,M會取到可能的最大值。現在Vani已經瞭解到了K的值,他希望你求出M的值,並給出字典序最小的感測器排布方案。

Input

  一個整數K。

 

Output

 一個整數M和一個二進位制串,由一個空格分隔。表示可能的最大的M,以及字典序最小的排布方案,字元0表示關,1表示開。你輸出的串的第一個字和最後一個字是相鄰的。

Sample Input

3

Sample Output

8 00010111

HINT

 得到的8個01串分別是000、001、010、101、011、111、110和100。注意前後是相鄰的。長度為3的二進位制串總共只有8種,所以M = 8一定是可能的最大值。


  對於全部測試點,2≤K≤11。

 

思路;我記得以前看到過這樣的題,資料比較大的情況下,有個什麼演算法專門做這個的,當時一大篇,沒看懂,叫什麼我都忘了,估計是論文題。

首先答案是2^K,即每個數都可以納進去。 然後考慮字典序最小,我們可以把這2^K個數看成邊,方向是首位指向末位,這樣的話每個點的度數一定為偶數,所以存在歐拉回路,資料比較小,我們暴搜就ok了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int vis[maxn],a[maxn],N;
bool dfs(int pos,int now)
{
    a[pos]=now&1; vis[now]=1;
    if(pos==(1<<N)) return true;
    int tmp=now; if(now&(1<<(N-1))) tmp-=(1<<(N-1));
    if(!vis[tmp*2]){
        if(dfs(pos+1,tmp*2)) return true;
        vis[tmp*2]=0;
    }
    if(!vis[tmp*2+1]){
        if(dfs(pos+1,tmp*2+1)) return true;
        vis[tmp*2+1]=0;
    }
    return false;
}
int main()
{
    scanf("%d",&N);
    printf("%d ",1<<N);
    dfs(N,0);
    for(int i=1;i<N;i++) putchar('0'); a[(1<<N)]=1;
    for(int i=N;i<=(1<<N);i++) printf("%d",a[i]);
    return 0;
}