【NOIP2013模拟】太鼓达人

版权声明:小编为此付出三天三夜(假的)请不要不请自用 https://blog.csdn.net/HfindH/article/details/81042105

题目描述

七夕祭上,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.

猜你喜欢

转载自blog.csdn.net/HfindH/article/details/81042105
今日推荐