[题目来源]:VIjos
[关键字]:动态规划
[题目大意]:用n块水晶搭建两个塔,要求双塔必须一样高,问最大能达到的高度为多少。
//============================================================================================================
[分析]:用f[i,j]表示使用前i个水晶,建起高度差为j的双塔时,较矮的那个塔的最大高度是多少。这样的话,对于每一块水晶都有三种决策,不使用,放到高塔上,放到矮塔上.而放到矮塔上会有两种情况,一是使矮塔的高度超过了高塔,二是没有超过。具体如下:
if f[1-t,j]>f[t,j] then f[t,j]:=f[1-t,j];//不使用
if f[1-t,j]>f[t,j+h[i]] then f[t,j+h[i]]:=f[1-t,j];//高塔
if j>=h[i]//判断会不会使矮塔变成高塔
then
begin
if f[1-t,j]+h[i]>f[t,j-h[i]] then f[t,j-h[i]]:=f[1-t,j]+h[i];
end//不会
else
begin
if f[1-t,j]+j>f[t,h[i]-j] then f[t,h[i]-j]:=f[1-t,j]+j;
end;//会
这样DP就可以了。边界是f[0,0]:=0;目标是f[n,0];
//出自tyvj1114题解
//==========================================================================================================
[代码]:
1 program Project1;
2 var
3 n: longint;
4 a, s: array[0..200] of longint;
5 f: array[0..200,0..2500] of longint;
6
7 procedure init;
8 var
9 i: longint;
10 begin
11 readln(n);
12 for i := 1 to n do read(a[i]);
13 for i := 1 to n do s[i] := s[i-1]+a[i];
14 end;
15
16 procedure work;
17 var
18 i, j: longint;
19 begin
20 fillchar(f,sizeof(f),200);
21 f[0,0] := 0;
22 for i := 1 to n do
23 for j := 0 to s[i] do
24 begin
25 if f[i-1,j] > f[i,j] then f[i,j] := f[i-1,j];
26 if f[i-1,j] > f[i,j+a[i]] then f[i,j+a[i]] := f[i-1,j];
27 if j >= a[i] then
28 if f[i-1,j]+a[i] > f[i,j-a[i]] then f[i,j-a[i]] := f[i-1,j]+a[i];
29 if j < a[i] then
30 if f[i-1,j]+j > f[i,a[i]-j] then f[i,a[i]-j] := f[i-1,j]+j;
31 end;
32 if f[n,0] > 0 then writeln(f[n,0]) else writeln('Impossible');
33 end;
34
35 begin
36 assign(input,'c:\1.in');reset(input);
37 assign(output,'c:\1.out');rewrite(output);
38 init;
39 work;
40 close(input);
41 close(output);
42 end.