您的位置:首页 > 其它

环形石子合并问题 - 经典DP问题

2012-06-21 09:34 351 查看







============================================================

又是一道超经典的题目。

对于线性的合并石子问题,dp模型类似于“加括号”那类型的dp题目,设 f(i,j)为 将第i项到第j项合并得到的最优解

关键是,这题目是环形的。环形结构,经常采用双倍长度线性化手段,也就是说,把环形结构看成是长度为环的两倍的线性结构来处理。

环的长度是N,所以题目相当于有一排石子1....N+N,然后就可以用线性的石子合并问题的方法做了。

有个要注意的地方,f(i,j) 总是与 f(N +i, N +j) 相等的,所以可以减少一些不必要的计算。

view
source

print?

01
#include
<cstdio>
02
#include
<algorithm>
03
using
namespace
std;
04
05
int
_sum[205];
06
int
a[205];
07
int
N;
08
int
f[205][205];
09
int
g[205][205];
10
11
int
getSegmentSum(
int
i,
int
j)
{
12
return
_sum[j]
- _sum[i] + a[i];
13
}
14
15
16
int
dp(
int
i,
int
j)
{
17
int
&
ans = f[i][j];
18
if
(ans
!= -1)
return
ans;
19
20
if
(i
== j)
return
ans
= 0;
21
if
(i
+ 1 == j)
return
ans
= getSegmentSum(i , j);
22
if
(i
<= N && j <= N)
return
ans
= dp(N + i,N + j);
23
24
ans
= 2000000000;
25
int
s
= getSegmentSum(i,j);
26
for
(
int
k
= i; k < j; ++k) {
27
ans
= min(ans, dp(i,k) + dp(k + 1, j) + s);
28
}
29
return
ans;
30
31
}
32
33
34
int
dp2(
int
i,
int
j)
{
35
int
&
ans = g[i][j];
36
if
(ans
!= -1)
return
ans;
37
38
if
(i
== j)
return
ans
= 0;
39
if
(i
+ 1 == j)
return
ans
= getSegmentSum(i , j);
40
if
(i
<= N && j <= N)
return
ans
= dp2(N + i,N + j);
41
42
ans
= -2000000000;
43
int
s
= getSegmentSum(i,j);
44
for
(
int
k
= i; k < j; ++k) {
45
ans
= max(ans, dp2(i,k) + dp2(k + 1, j) + s);
46
}
47
return
ans;
48
49
}
50
51
52
void
input()
{
53
int
i,
j;
54
scanf
(
"%d"
,
&N);
55
for
(i
= 1; i <= N; ++i) {
56
scanf
(
"%d"
,
&(a[i]));
57
}
58
for
(i
= N + 1; i <= N + N; ++i) a[i] = a[i - N];
59
_sum[1]
= a[1];
60
for
(i
= 2; i <= N + N; ++i) _sum[i] = a[i] + _sum[i - 1];
61
62
for
(i
= 0; i < 205; ++i)
63
for
(j
= 0; j < 205; ++j)
64
f[i][j]
= g[i][j] = -1;
65
66
67
}
68
69
int
main()
{
70
input();
71
int
i,
j;
72
for
(i
= N + N; i >= 1; --i)
73
for
(j
= i; j <= N + N; ++j)
74
{
dp(i,j); dp2(i,j); }
75
76
int
ans
= 2000000000;
77
for
(i
= 1; i <= N; ++i) {
78
ans
= min(ans, dp(i,i + N - 1));
79
}
80
81
int
ans2
= -2000000000;
82
for
(i
= 1; i <= N; ++i) {
83
ans2
= max(ans2, dp2(i,i + N - 1));
84
}
85
printf
(
"%d\n%d\n"
,
ans, ans2);
86
return
0;
87
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: