[二分答案] Copying Books

上次做到那个收入计划的时候就提到了这道题目,在POJ上是让输出方案,并且保证前面的人赋值的书稿尽量多。所以不需要SJ。

具体实现就是先二分出正确的答案,然后根据答案从后往前进行贪心划分。

[pascal 代码]

VAR
        A,WAY:ARRAY[0..100000]OF LONGINT;
        N,M,L,R,MID,I,J,TOT,T,IT:LONGINT;
FUNCTION CHECK(P:LONGINT):BOOLEAN;
 VAR
        PRE,I:LONGINT;
 BEGIN
        TOT:=M;
        PRE:=0;
        I:=1;
        WHILE I<=N DO
                BEGIN
                        IF PRE+A[I]<=P THEN
                                BEGIN
                                        PRE:=PRE+A[I];
                                        INC(I);
                                END
                        ELSE
                                BEGIN
                                        PRE:=0;
                                        DEC(TOT);
                                        IF TOT=0 THEN EXIT(FALSE);
                                END;
                END;
        EXIT(TRUE);
 END;
PROCEDURE GETWAYS(P:LONGINT);
 VAR
        PRE,I,TOT:LONGINT;
 BEGIN
        TOT:=0;
        PRE:=0;
        I:=N;
        WHILE I>=1 DO
                BEGIN
                        IF (PRE+A[I]<=P)AND(M-TOT<=I) THEN
                                BEGIN
                                        PRE:=PRE+A[I];
                                        DEC(I);
                                END
                        ELSE
                                BEGIN
                                        PRE:=0;
                                        INC(TOT);
                                        WAY[TOT]:=I;
                                        IF TOT=0 THEN EXIT;
                                END;
                END;
 END;
BEGIN
        READLN(T);
        FOR IT:=1 TO T DO
        BEGIN
        READLN(N,M);
        R:=0;L:=0;
        FOR I:=1 TO N DO
                BEGIN
                        READ(A[I]);
                        R:=R+A[I];
                END;
        WHILE L<R DO
                BEGIN
                        MID:=(L+R)>>1;
                        IF CHECK(MID) THEN R:=MID ELSE L:=MID+1;
                END;
        //WRITELN(L);
        GETWAYS(L);
        L:=1;
        FOR I:=M-1 DOWNTO 1 DO
                BEGIN
                        R:=WAY[I];
                        FOR J:=L TO R DO WRITE(A[J],' ');WRITE('/ ');
                        L:=R+1;
                END;
        FOR I:=L TO N DO WRITE(A[I],' ');WRITELN;
        END;
END.
posted @ 2011-10-29 08:53  NoRush  阅读(332)  评论(0编辑  收藏  举报