1. 程式人生 > >【NOIP2013模擬】太鼓達人

【NOIP2013模擬】太鼓達人

題目描述

七夕祭上,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的值,並給出字典序最小的感測器排布方案。

思路

我們可以先將所有的01串按字典序從小到大做出來。我們很容易發現(打表找規律),將全0串放最前面明顯是最優的。所以,我自然而然地想到了貪心。

解法

我們先設f[i],將01串按上述做好。設m[i]為第i次檢查出的01串是f陣列中的第m[i]個,DG判斷是否能放入,可以就往下DG。如果方案成立直接輸出。

注意

當dg查詢到第X層(x>2^n-n+1)時,我們就要特殊處理,因為查詢會迴圈到頭,所以我們要判斷在末尾的那段是否成立,且該01串結尾是否都為0。

var
        n,k,i,j,o,l,q:longint;
        bz:array[1..4096
]of boolean; m:array[1..4096]of longint; p:char; ans,g:ansistring; f:array[1..4096]of string; procedure dg(x:longint); var i,j,w:longint; bj:boolean; begin if (x=k+1) then begin write(k,' ',f[1]); for i:=2 to
k-n+1 do write(f[m[i],n]); writeln; halt; end; if (x>k-n+1) then w:=k-x+1 else w:=n-1; for i:=1 to k do begin bj:=false; if (bz[i]=false) then begin for j:=1 to w do begin if (f[i,j]<>f[m[x-1],j+1]) then begin bj:=true; break; end; end; if (w<>n-1) then begin for j:=w+1 to n do if (f[i,j]<>'0') then bj:=true; end; if (bj=false) then begin bz[i]:=true; m[x]:=i; dg(x+1); bz[i]:=false; end; end; end; end; begin readln(n); k:=1; for i:=1 to n do k:=k*2; o:=k div 2; while (o<>0) do begin p:='1'; l:=1; for i:=1 to k div o do begin q:=(ord(p)-47)mod 2; p:=chr(q+48); for j:=l to l+o-1 do f[j]:=f[j]+p; inc(l,o); end; o:=o div 2; end; ans:='2'; m[1]:=1; bz[1]:=true; dg(2); end.