[题目来源]:NOIP2003普及组
[关键字]:动态规划
[题目大意]:将一个n个数字组成的环分成m份,使每份之和对10取模后相乘的积最大或最小。
//======================================================================
[分析]:类似于石子合并的动态规划,解法比较暴力(n<=50 m<=9)。枚举每一个点,以此为起点将环断开,然后f[i,j]为以枚举断链的点开始前i个分成j组的最大(最小值),f[i,j]=f[k,j-1]*sum[k+1,i],具体i,j,k所代表的含义有点不同,结合代码再仔细看吧。
[代码]:
1 var
2 n, m, ansa, ansi: longint;
3 max, min: array[0..50,0..10] of longint;
4 sum: array[0..50,0..50] of longint;
5 a: array[0..50] of longint;
6
7 function gmax(x, y: longint):longint;
8 begin
9 if x > y then exit(x) else exit(y);
10 end;
11
12 function gmin(x, y: longint):longint;
13 begin
14 if x < y then exit(x) else exit(y);
15 end;
16
17 procedure init;
18 var
19 i, j, st, ed, mid: longint;
20 begin
21 readln(n,m);
22 for i := 1 to n do read(a[i]);
23 for i := 1 to n do
24 for j := i to i+n-1 do
25 begin
26 st := i;
27 if j > n then ed := j-n else ed := j;
28 if ed-1 < 1 then mid := ed-1+n else mid := ed-1;
29 sum[st,ed] := sum[st,mid]+a[ed];
30 sum[st,ed] := sum[st,ed] mod 10;
31 if sum[st,ed] < 0 then inc(sum[st,ed],10);
32 end;
33 {for i := 1 to n do
34 for j := 1 to n do writeln(i,' ',j,' ',sum[i,j]);}
35 end;
36
37 procedure work;
38 var
39 st, i, mid, j, k, mid2: longint;
40 begin
41 ansa := 0;
42 ansi := maxlongint;
43 for st := 1 to n do
44 begin
45 fillchar(max,sizeof(max),0);
46 fillchar(min,sizeof(min),10);
47 for i := 1 to n do
48 begin
49 if st+i-1 > n then mid := st+i-1-n else mid := st+i-1;
50 max[i,1] := sum[st,mid];
51 min[i,1] := sum[st,mid];
52 //writeln(st,'',i,'',max[i,1]);
53 end;
54 for i := 1 to n do
55 for j := 2 to gmin(i,m) do
56 begin
57 for k := 1 to i-1 do
58 begin
59 if st+k > n then mid := st+k-n else mid := st+k;
60 if st+i-1 > n then mid2 := st+i-1-n else mid2 := st+i-1;
61 max[i,j] := gmax(max[i,j],max[k,j-1]*sum[mid,mid2]);
62 min[i,j] := gmin(min[i,j],min[k,j-1]*sum[mid,mid2]);
63 end;
64 //writeln(st,'',i,'',j,'',max[i,j]);
65 end;
66 //writeln(st,'',max[n,m],'',min[n,m]);
67 ansa := gmax(ansa,max[n,m]);
68 ansi := gmin(ansi,min[n,m]);
69 end;
70 //if ansi < 0 then ansi := 0;
71 writeln(ansi);
72 writeln(ansa);
73 end;
74
75 begin
76 assign(input,'d:\1.in');reset(input);
77 assign(output,'d:\1.out');rewrite(output);
78 init;
79 work;
80 close(input);
81 close(output);
82 end.