10 1 50 20 5
player might take a card with 1, then 20 and 50, scoring
10*1*50 + 50*20*5 + 10*50*5 = 500+5000+2500 = 8000
If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be
1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150.
不能取第一个和最后一个数字,我们的目的是将其余数字全部取出,并且使得按照规则计算的分数最小。
计分规则是,每取一个a, 计算 score.a = a.left * a * a.right然后将a取出,最后的总分是每次取出计算得出的分值总和。
动态规划,思路和矩阵连乘几乎一致。
考虑
10 1 50 20 5
对于最优解,取最后一个数字,假如说最后一个数字取的是50,那么其实
10 1 50
50 20 5
是两个子问题,他们也应该是最优的,而最后结果是
10 * 50 * 5 + best(10,1,50) + best(50,20,5)
best resutl of li = best[0, len – 1]
best[i, j] = min { li[i] * li[k] * li[j] + best[i, k] + best[k, j]} for k in range [i+1, j)
1
#include
<
iostream
>
2
using
namespace
std;
3
4
int
SolveDp(
int
a[],
int
num)
5
{
6
int
result[num][num];
7
for
(
int
i
=
0
; i
<
num; i
++
)
8
for
(
int
j
=
0
; j
<
num; j
++
)
9
result[i][j]
=
0
;
10
11
//
init delta = 2 a[0] a[1] a[2]
12
for
(
int
i
=
0
; i
<
num
-
2
; i
++
)
13
result[i][i
+
2
]
=
a[i]
*
a[i
+
1
]
*
a[i
+
2
];
14
15
for
(
int
delta
=
3
; delta
<
num; delta
++
)
16
for
(
int
i
=
0
; i
<
num
-
delta; i
++
) {
17
int
minScore;
18
for
(
int
j
=
i
+
1
; j
<
i
+
delta; j
++
) {
19
int
curScore
=
result[i][j]
+
result[j][i
+
delta]
+
20
a[i]
*
a[j]
*
a[i
+
delta];
21
if
(j
==
i
+
1
)
22
minScore
=
curScore;
23
else
if
(curScore
<
minScore)
24
minScore
=
curScore;
25
}
26
result[i][i
+
delta]
=
minScore;
27
}
28
return
result[
0
][num
-
1
];
29
}
30
31
int
main(
int
argc,
char
*
argv[])
32
{
33
//
while
(
1
) {
34
int
num;
35
cin
>>
num;
36
int
a[num];
37
for
(
int
i
=
0
; i
<
num; i
++
)
38
cin
>>
a[i];
39
cout
<<
SolveDp(a, num)
<<
endl;
40
//}
41
return
0
;
42
}
下面给出python写的,递归回溯(穷举),以及动态规划解法
1 #递归回溯穷举
2 def findMinScore(li):
3 minScore = -1 #init,if not touched it will be < 0
4 def findMinScoreRec(score = 0):
5 nonlocal minScore
6 length = len(li)
7 for i in range(1, length - 1):
8 val = li[i]
9 newScore = score + li[i - 1] * val * li[i + 1]
10 if not minScore < 0 and newScore > minScore:
11 return
12 if len(li) == 3:
13 if minScore <0 or newScore < minScore:
14 minScore = newScore
15 return
16 li.pop(i)
17 findMinScoreRec(newScore)
18 li.insert(i, val) #do not need to get back
19 print("min score is ", minScore);
20 findMinScoreRec();
21 return minScore
22 1 #dp method
2
def
findMinScore(li):
3
length
=
len(li)
4
#
below is wrong!!! when result[0][2] = 99 than result[i][2] = 99 why??
5
#
result = [[0] * length] * length #result[length][length] 0 is must for elements of distance 2
6
7
result
=
[[0
for
a
in
range(length)]
for
b
in
range(length)]
8
9
for
i
in
range(length
-
2
):
10
result[i][i
+
2
]
=
li[i]
*
li[i
+
1
]
*
li[i
+
2
]
11
12
for
delta
in
range(
3
, length):
13
for
i
in
range(length
-
delta):
14
for
j
in
range(i
+
1
, i
+
delta):
15
curScore
=
result[i][j]
+
result[j][i
+
delta] \
16
+
li[i]
*
li[j]
*
li[i
+
delta]
17
if
(j
==
i
+
1
or
curScore
<
minScore):
18
minScore
=
curScore
19
result[i][i
+
delta]
=
minScore
20
21
return
result[0][length
-
1
]
22