上次做到那个收入计划的时候就提到了这道题目,在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.