1812. 【提高組NOIP2008】雙棧排序 (twostack.pas/c/cpp)

1812. 【提高組NOIP2008】雙棧排序 (twostack.pas/c/cpp)

Tom最近在研究一個有趣的排序問題。如圖所示,通過2個棧S1和S2,Tom希望藉助以下4種操作實現將輸入序列升序排序。

操作a

如果輸入序列不爲空,將第一個元素壓入棧S1

操作b

如果棧S1不爲空,將S1棧頂元素彈出至輸出序列

操作c

如果輸入序列不爲空,將第一個元素壓入棧S2

操作d

如果棧S2不爲空,將S2棧頂元素彈出至輸出序列

如果一個1~n的排列P可以通過一系列操作使得輸出序列爲1,2,…,(n-1),n,Tom就稱P是一個“可雙棧排序排列”。例如(1,3,2,4)就是一個“可雙棧排序序列”,而(2,3,4,1)不是。下圖描述了一個將(1,3,2,4)排序的操作序列:

當然,這樣的操作序列有可能有幾個,對於上例(1,3,2,4),是另外一個可行的操作序列。Tom希望知道其中字典序最小的操作序列是什麼。

輸入

輸入文件twostack.in的第一行是一個整數n。

第二行有n個用空格隔開的正整數,構成一個1~n的排列。

輸出

輸出文件twostack.out共一行,如果輸入的排列不是“可雙棧排序排列”,輸出數字0;否則輸出字典序最小的操作序列,每兩個操作之間用空格隔開,行尾沒有空格。

樣例輸入

【輸入輸出樣例1】

4

1 3 2 4

【輸入輸出樣例2】

4

2 3 4 1

【輸入輸出樣例3】

3

2 3 1

樣例輸出

【輸入輸出樣例1】

a b a a b b a b

【輸入輸出樣例2】

0

【輸入輸出樣例3】

a c a b b d

數據範圍限制

【限制】

30%的數據滿足: n<=10

50%的數據滿足: n<=50

100%的數據滿足: n<=1000

一道蠻坑的題目。。。。。

比賽思路:亂打。(三個樣例沒過)

期望得分:

(最高):100

(最低):0

結果出來,

9.1分。呵呵噠…….

轉入正題

正解:玄學之二分圖染色

具體操作

(1)連邊。如果a[k] < a[i] < a[j]且i< j< k,將i與j連邊;

(連邊的意思是不可以在同一個棧裏)

方法:記錄一下b[i,j](i後有沒有a[j]),o(2n^2)解決;

(2)入棧:先記錄c[i](代表a[i]的狀態,0自由,1在1棧,2在2棧)如果c[i]=0,c[i]入1棧並將於c[i]連邊的點入2棧。

Warning:給出一組數據:

(if c[i]=0 then)

10

10 2 8 1 7 9 3 4 5 6

2-8,8-9,7-9連邊

i=1時,10入1棧;

i=2時,2入1棧,8入2棧;

i=3時,8已經在2棧,7入1棧,2不用入1棧(已入);

i=4時,1入1棧;

i=5時,7入1棧(?),9入2棧!

但,8與9不能進一個棧!

難道輸出0?

不對,7可以入2棧,那麼9入1棧,成立。

這種”被迫“入2棧的例子,要判斷。

設要入棧的點爲i,i的連邊點有j。

if c[j]=1 then i入2棧。

如果i入2棧都不行,輸出0.

if c[i]=1 then 將i的所有連邊點j,c[j]=2;

if c[i]=2 then 將i的所有連邊點j,c[j]=1;

(3)出棧。

t=0;

inc(t);if c[t]=0 then break;(if c[t]=1 then s:=s+’b ’ ;if c[t]=2 then s:=s+’d ‘;)

就這樣,直到t>=n,退出程序。

做完了。

注意:

1:連雙向邊;

2:細節!

3:那些字符要用s儲存,不要直接輸出。

4:字典序時,可能a操作比d先,要判斷。(否則90.9)

代碼:

請勿抄襲:(6293 bytes)

var
        f:array[1..100000,1..2] of longint;
        x,y:array[0..10000] of longint;
        a,q:array[1..10000] of longint;
        b:array[1..1000,1..1000] of longint;
        c,d:array[1..100000] of longint;
        i,j,k,m,n,o,p,l,s1,t,min:longint;
        bz:boolean;
        zu:array[1..1000,1..1000] of boolean;
        g:array[0..10000] of boolean;
        s:ansistring;
procedure insert(x,y:longint);
begin
        inc(t);
        f[t,1]:=y;
        f[t,2]:=q[x];
        q[x]:=t;
end;
begin
        assign(input,'twostack.in');reset(input);
        assign(output,'twostack.out');rewrite(output);
        readln(n);
        for i:=1 to n do read(a[i]);
        for i:=1 to n do begin
                min:=maxlongint;
                for j:=i+1 to n do
                        if a[j]<min then begin
                                min:=a[j];
                        end;
                if min=maxlongint then continue;
                for j:=min+1 to n do b[i,j]:=1;
                for j:=1 to min do b[i,j]:=0;
        end;
        fillchar(zu,sizeof(zu),true);
        fillchar(g,sizeof(g),true);
        for i:=1 to n do begin
                for j:=i+1 to n do begin
                        if a[i]<a[j] then begin
                                if b[j,a[i]]=1 then begin
                                        insert(a[i],a[j]);
                                        writeln(a[i],' ',a[j]);
                                        zu[a[i],a[j]]:=false;zu[a[j],a[i]]:=false;
                                end;
                        end;
                end;
        end;
        s1:=1;  t:=0;
        for i:=1 to n do begin
                if g[i]=false then continue;
                if c[a[i]]=0 then begin
                        d[a[i]]:=x[0];
                        k:=q[a[i]];
                        bz:=true;
                        while k<>0 do begin
                                if c[f[k,1]]=1 then begin
                                        bz:=false;
                                end;
                                if bz=false then break;
                                k:=f[k,2];
                        end;
                        k:=q[a[i]];
                        if bz=true then begin
                                s:=s+'a ';
                                inc(x[0]);
                                x[x[0]]:=a[i];c[a[i]]:=1;
                                while k<>0 do begin
                                        if c[f[k,1]]=0 then begin
                                                inc(y[0]);
                                                y[y[0]]:=f[k,1];
                                                c[f[k,1]]:=2;
                                                d[a[i]]:=y[0];
                                        end;
                                        k:=f[k,2];
                                end;
                        end else begin
                                s:=s+'c ';
                                inc(y[0]);
                                y[y[0]]:=a[i];c[a[i]]:=2;
                                while k<>0 do begin
                                        if c[f[k,1]]=0 then begin
                                                inc(x[0]);
                                                x[x[0]]:=f[k,1];
                                                c[f[k,1]]:=1;
                                        end;
                                        k:=f[k,2];
                                end;
                        end;
                end else if c[a[i]]=1 then begin
                        s:=s+'a ';
                        k:=q[a[i]];
                        while k<>0 do begin
                                if c[f[k,1]]=1 then begin
                                        writeln(0);
                                        close(input);close(output);
                                        halt;
                                end;
                                if c[f[k,1]]=0 then begin
                                        inc(y[0]);
                                        y[y[0]]:=f[k,1];
                                        c[f[k,1]]:=2;
                                        //s:=s+'c ';
                                end;
                                k:=f[k,2];
                        end;
                end else begin
                        k:=q[a[i]];
                        s:=s+'c ';
                        while k<>0 do begin
                                if c[f[k,1]]=2 then begin
                                        writeln(0);
                                        close(input);close(output);
                                        halt;
                                end;
                                if c[f[k,1]]=0 then begin
                                        inc(x[0]);
                                        x[x[0]]:=f[k,1];
                                        c[f[k,1]]:=1;
                                        //s:=s+'a ';
                                end;
                                k:=f[k,2];
                        end;
                end;
                t:=s1;
                j:=s1;
                repeat
                        if j=0 then continue;
                        if c[j]<>0 then begin
                                if c[j]=1 then begin
                                        s:=s+'b ';
                                        inc(j);
                                        dec(x[0]);
                                end
                                else begin
                                        if x[0]=0 then begin
                                                s:=s+'a ';
                                                inc(x[0]);x[x[0]]:=a[i+1];c[i+1]:=1; g[i+1]:=false;
                                                s:=s+'d ';

                                        end else s:=s+'d ';
                                        inc(j);
                                end;
                        end;
                        if c[j]=0 then begin
                                t:=j;
                                break;
                        end;
                until j>n;
                s1:=t;
                //writeln(s);
        end;
        writeln(s);
        close(input);close(output);
end.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章