在线评测:
http://codevs.cn/problem/1017/
整体思路:
这道题看起来挺水的,,一个n3k2的算法都过了。。。就dp一下。dpi j q 表示区间i——j用q个乘法能获得的最大值。
开始预处理出所以的原始值。既不用乘号就能算出的值,,然后dp一下就好了,枚举当前dp区间的中的一个点,将其分为两半,枚举其中一半的乘号数目,然后max所有枚举出的区间对的最大值就好了。。。记得dp找区间对的时候乘号数目是要少一个的,,,,
失误之处:
输入的数据间没空格,,然而没注意。蒙蔽了半天。
每次将一个区间拆成两个的时候,没有将其的乘号数目减少1个,,,,
体会心得:
看好输入!看好输出!
仔细想状态转移方程的实际意义,每一个细节都要搞明白才行。。。
AC代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using
namespace
std;
int
n,k,sz[50],dp[50][50][10];
char
tp[100];
int
jq(
int
s,
int
t)
{
int
tot = 0;
for
(
int
i = s;i <= t;i++)
{
tot *= 10;
tot += sz[i];
}
return
tot;
}
int
main()
{
scanf
(
"%d%d"
,&n,&k);
scanf
(
"%s"
,tp);
for
(
int
i = 0;i < n;i++)
{
sz[i + 1] = tp[i] -
'0'
;
}
for
(
int
i = 1;i <= n;i++)
{
for
(
int
j = 1;j <= n;j++)
{
if
(j + i - 1 <= n)
{
dp[j][j+i-1][0] = jq(j,j+i-1);
}
}
}
for
(
int
i = 1;i < n;i++)
for
(
int
j = i + 1;j <= n;j++)
for
(
int
q = 1;q <= k;q++)
{
int
maxn = 0;
for
(
int
o = i;o < j;o++)
for
(
int
p = 0;p <= q - 1;p++)
{
maxn = max(maxn,dp[i][o][p] * dp[o+1][j][q - p - 1]);
}
dp[i][j][q] = maxn;
}
printf
(
"%d\n"
,dp[1][n][k]);
return
0;
}
|