【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.
如果自己说什麽都做不到而什麽都不去做的话,那就更是什麽都做不到,什麽都不会改变,什麽都不会结束.