Ural1005
http://hi.baidu.com/raulliubo/blog/item/61a2868284bfbdbd6d811902.html
Time Limit: 2.0 second
Memory Limit: 16 MB
You have a number of stones with known weights W1…Wn. Write a program that will rearrange the stones into two piles such that weight difference between the piles is minimal.
Input
Input contains the number of stones N (1 ≤ N ≤ 20) and weights of the stones W1…Wn (1 ≤ Wi ≤ 100000) delimited by white spaces.
Output
Your program should output a number representing the minimal possible weight difference between stone piles.
Sample
input
|
output
|
---|---|
5 5 8 13 27 14 |
3 |
其实就是搜。。深搜就可以了。。
var w:array[1..20] of longint;
n,i:longint;
s,tot,min:longint;
procedure search(i:longint);
begin
if i=n then begin
if abs(tot-s*2)<min then min:=abs(tot-s*2) end
else begin
search(i+1);
inc(s,w[i]);
search(i+1);
dec(s,w[i]);
end;
end;
begin
tot:=0;
read(n);
for i:=1 to n do begin
read(w[i]);
inc(tot,w[i]);
end;
min:=tot; s:=0;
search(1);
writeln(min);
end.
题在上一篇文章中。
上一篇中,因数据规模极小,我用深搜就将其搞定。
为了练习自己的dp。我今天又将其做了一遍。
我们可以设一个boolean数组f,0..(20*100000 div 2)//就是石子总重量的一半。
用其表示石子可以合并成的重量。
初始化f[0]为true;f[i]:=f[i+w[j]] or f[i] or f[i-w[j]];很好理解。
可以简化一下。就是f[i]:=f[i] or f[i-w[j];与上面的一个效果。
算完这步后,我们再算小于总重量一半的最大重量;设i=总重量的一半。然后dec(i)直到f[i]为true。
就找到了最大的小于总重量一半的i。
然后ans就是总重量减去i的两倍。//这也很好理解。
附程序:
----------------------------------------------------my program----------------------------------------------------
{
PROG:URAL1005
ID:parachutes
STATE:AC
}
var w:array[0..20] of longint;
f:array[0..1000000] of boolean;
n,i,total,j,sum:longint;
begin
total:=0;
read(n);
for i:=1 to n do begin
read(w[i]);
total:=total+w[i];
end;//读入数据并算总重量。
sum:=total div 2;
for i:=1 to sum do f[i]:=false; f[0]:=true; //初始化数组f。
for i:=1 to n do
for j:=sum downto w[i] do
f[j]:=f[j] or f[j-w[i]];
i:=sum;
while (f[i]=false) and (i>0) do dec(i);//算最大的i。
writeln(total-2*i);
end.