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.