還記得那一年倒水的廣搜題嘛~

mok 
題目描述  
N個杯子,第i個容量爲Vi,一開始所有杯子裝滿水,每次可以 
1) 將一個杯子中的水倒掉。 
2) 將杯子A中的水全部倒入杯子B(如果不會溢出的話)。 
3) 用杯子A中部分的水填滿杯子B(如果夠的話)。 
問能否通過若干次倒水得到目標狀態。 
輸入文件  
第一行N 表示杯子個數 
第二行N個數 表示每個杯子的容量 
第三行N個數 表示目標狀態中每個杯子的水量 
輸出文件  
  
若可以,輸出最少步數,否則輸出NIE 
 
樣例輸入  
3 
3 5 5 
0 0 4 
樣例輸出  
6 
 
數據約定  
100%:N<=4,1<=Vi<=50 

覺得過於不屑以及LZSB的請 滾出 + <Ctrl + W>












排除了許多不和諧因素之後進入正題

記得當初是三個桶子

記得當初廣搜寫得醜得和一坨翔一樣

獻上mt的神code 真心覺得寫得好!!!

用C++重寫一遍的話就感覺不那麼神了, 於是還是貼mt的原代碼!!!


program mt;
const
  inf = 'mok.in';
  ouf = 'mok.out';
var
  l, r: array[1 .. 4] of longint;
  q: array[1 .. 150000, 1 .. 4] of longint;
  f: array[0 .. 49, 0 .. 49, 0 .. 49, 0 .. 49] of longint;
  i, j, k, ff, rr, n: longint;

procedure ins;
begin
  if f[r[1], r[2], r[3], r[4]] < 0 then begin
    f[r[1], r[2], r[3], r[4]] := k + 1;
    inc(rr); q[rr] := r
    end;
end;

BEGIN
  assign(input, inf); reset(input);
  assign(output, ouf); rewrite(output);

  read(n);
  for i := 1 to n do read(l[i]);
  fillchar(f, sizeof(f), $FF);
  k := -1; r := l; ins;
  while ff < rr do begin
    inc(ff);
    r := q[ff];
    k := f[r[1], r[2], r[3], r[4]];
    for i := 1 to n do
      for j := 1 to n do
        if (i <> j) and (q[ff, j] <> l[j]) then begin
          r := q[ff];
          if r[i] + r[j] <= l[j] then begin
            r[j] := r[j] + r[i]; r[i] := 0;
            end
          else begin
            r[i] := r[i] - l[j] + r[j]; r[j] := l[j];
            end;
          ins
          end;
    for i := 1 to n do
      if q[ff, i] > 0 then begin
        r := q[ff]; r[i] := 0;
        ins;
        end;
    end;
  for i := 1 to n do read(r[i]);
  if f[r[1], r[2], r[3], r[4]] >= 0 then writeln(f[r[1], r[2], r[3], r[4]])
  else writeln('NIE');

  close(input); close(output);
END.


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