1. 程式人生 > >(4)碎紙機(p.pas/c/cpp)

(4)碎紙機(p.pas/c/cpp)

(4)碎紙機(p.pas/c/cpp)

【描述】

你現在負責設計一種新式的碎紙機。一般的碎紙機會把紙切成小片,變得難以閱讀。而你設計的新式的碎紙機有以下的特點:

1.每次切割之前,先要給定碎紙機一個目標數,而且在每張被送入碎紙機的紙片上也需要包含一個數。
2.碎紙機切出的每個紙片上都包括一個數。
3.要求切出的每個紙片上的數的和要不大於目標數而且與目標數最接近。

舉一個例子,如下圖,假設目標數是50,輸入紙片上的數是12346。碎紙機會把紙片切成4塊,分別包含1,2,34和6。這樣這些數的和是43 (= 1 + 2 + 34 + 6),這是所有的分割方式中,不超過50,而又最接近50的分割方式。又比如,分割成1,23,4和6是不正確的,因為這樣的總和是34 (= 1 + 23 + 4 + 6),比剛才得到的結果43小。分割成12,34和6也是不正確的,因為這時的總和是52 (= 12 + 34 + 6),超過了50。


還有三個特別的規則:
1.如果目標數和輸入紙片上的數相同,那麼紙片不進行切割。
2.如果不論怎樣切割,分割得到的紙片上數的和都大於目標數,那麼印表機顯示錯誤資訊。
3.如果有多種不同的切割方式可以得到相同的最優結果。那麼印表機顯示拒絕服務資訊。比如,如果目標數是15,輸入紙片上的數是111,那麼有兩種不同的方式可以得到最優解,分別是切割成1和11或者切割成11和1,在這種情況下,印表機會顯示拒絕服務資訊。


為了設計這樣的一個碎紙機,你需要先寫一個簡單的程式模擬這個印表機的工作。給定兩個數,第一個是目標數,第二個是輸入紙片上的數,你需要給出碎紙機對紙片的分割方式。

【輸入】

輸入包括多組資料,每一組包括一行。每行上包括兩個正整數,分別表示目標數和輸入紙片上的數。已知輸入保證:兩個數都不會以0開頭,而且兩個數至多都只包含6個數字。

輸入的最後一行包括兩個0,這行表示輸入的結束。

【輸出】

對每一組輸入資料,輸出相應的輸出。有三種不同的輸出結果:

sum part1 part2 ...
rejected
error

第一種結果表示:
1.每一個partj是切割得到的紙片上的一個數。partj的順序和輸入紙片上原始數中數字出現的次序一致。
2.sum是切割得到的紙片上的數的和,也就是說:sum = part1 + part2 +...
第一種結果中相鄰的兩個數之間用一個空格隔開。

如果不論怎樣切割,分割得到的紙片上數的和都大於目標數,那麼列印“error”。
如果有多種不同的切割方式可以得到相同的最優結果,那麼列印“rejected”。

【樣例輸入】

50 12346

376 144139

927438 927438

18 3312

9 3142

25 1299

111 33333

103 862150

6 1104

0 0

【樣例輸出】

43 1 2 34 6

283 144 139

927438 927438

18 3 3 12

error

21 1 2 9 9

rejected

103 86 2 15 0

rejected

【自己題解】

var
  a,b,i,j,sum,min,n,p:longint;
  k:array[1..1000] of longint;
  best:array[1..1000] of longint;
  s:string;
  flag,t:boolean;
procedure pin(s:string);
begin
 assign(input,s+'.in');reset(input);
 assign(output,s+'.out');rewrite(output);
end;
procedure pout;
begin
 close(input);close(output);
end;
procedure dfs(dep:longint;st:string);
var
  count,i:longint;
begin
  if (dep>length(s)) then
  begin
    inc(n);
    if (st<>'') then val(st,k[n]);
    count:=0;
    for i:=1 to n do
    count:=count+k[i];
    if (count<=a) and (a-count<min) then
    begin
      min:=a-count;
      for i:=1 to n do
      best[i]:=k[i];
      flag:=true;
      t:=true;
      p:=n;
    end
    else if (count<=a) and (a-count=min) then flag:=false;
    dec(n);
  end
  else
  begin
    if (st<>'') then
    begin
      inc(n);
      val(st,k[n]);
      dfs(dep+1,s[dep]);
      dec(n);
    end;
    dfs(dep+1,st+s[dep]);
  end;
end;
begin
  pin('p');
  while (true) do
  begin
    t:=false;
    flag:=true;
    n:=0;
    min:=maxlongint;
    read(a,b);
    if (a=0) and (b=0) then break;
    if (a=b) then writeln(a,' ',b)
    else
    begin
      str(b,s);
      dfs(1,'');
      if (t=false) then writeln('error')
      else if (flag=false) then writeln('rejected')
      else
      begin
        write(a-min);
        for i:=1 to p do
        write(' ',best[i]);
        writeln;
      end;
    end;
  end;
  pout;
end.