加
法
最
大
加法最大
加 法 最 大
Description
设有一个长度为n的数字字符串,分成k+1个部份,使其k+1部份相加的和为最大。例如:数字串’340670’,k=1,其加法有
3+40670=40673 34+0670=704 340+670=1010 3406+70=3476 34076+0=34076
其最大和为40676。
问题:当数字串和k给出后,找出一个分法使和为最大。
Sample Input
6 1
340670
Sample Output
40673
题
目
大
意
:
{\color{Red}题目大意:}
题 目 大 意 :
有
一
个
长
度
为
n
的
数
字
字
符
串
,
要
求
插
入
k
个
加
号
{\color{Red}有一个长度为n的数字字符串,要求插入k个加号}
有 一 个 长 度 为 n 的 数 字 字 符 串 , 要 求 插 入 k 个 加 号
(
不
能
在
最
前
面
和
最
后
面
)
,
求
结
果
最
大
是
多
少
{\color{Red}(不能在最前面和最后面),求结果最大是多少}
( 不 能 在 最 前 面 和 最 后 面 ) , 求 结 果 最 大 是 多 少
解题方法:
我们插入加号可以在已经有的加号右边直接加,因为都是加号 然后在右方的每一个位置都枚举一遍(要先求出第i到第j的数字是多少),即可
初始化:
f
[
i
]
[
0
]
=
f
[
i
−
1
]
[
0
]
∗
10
+
d
[
i
]
;
f[i][0]=f[i-1][0]*10+d[i];
f [ i ] [ 0 ] = f [ i − 1 ] [ 0 ] ∗ 1 0 + d [ i ] ;
状态转移方程:
f
[
i
]
[
k
]
=
m
a
x
(
f
[
i
]
[
k
]
,
f
[
j
]
[
k
−
1
]
+
s
[
j
+
1
]
[
i
]
)
;
f[i][k]=max(f[i][k],f[j][k-1]+s[j+1][i]);
f [ i ] [ k ] = m a x ( f [ i ] [ k ] , f [ j ] [ k − 1 ] + s [ j + 1 ] [ i ] ) ;
注释:
f[i][k]表示前i个数加k个加号的最大值
#include <cstdio>
#include <iostream>
using namespace std;
int f[ 100 ] [ 100 ] , s[ 100 ] [ 100 ] , d[ 100 ] , n, m;
int main ( )
{
scanf ( "%d%d" , & n, & m) ;
getchar ( ) ;
for ( int i= 1 ; i<= n; i++ )
{
d[ i] = getchar ( ) - 48 ;
f[ i] [ 0 ] = f[ i- 1 ] [ 0 ] * 10 + d[ i] ;
}
for ( int i= 1 ; i<= n; i++ )
{
s[ i] [ i] = d[ i] ;
for ( int j= i+ 1 ; j<= n; j++ )
s[ i] [ j] = s[ i] [ j- 1 ] * 10 + d[ j] ;
}
for ( int k= 1 ; k<= m; k++ )
for ( int i= k+ 1 ; i<= n- m+ k; i++ )
for ( int j= k; j< i; j++ )
f[ i] [ k] = max ( f[ i] [ k] , f[ j] [ k- 1 ] + s[ j+ 1 ] [ i] ) ;
printf ( "%d" , f[ n] [ m] ) ;
}
乘
积
最
大
乘积最大
乘 积 最 大
Description
今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:
设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:
有一个数字串:312, 当N=3,K=1时会有以下两种分法:
1) 3*12=36
2) 31*2=62
这时,符合题目要求的结果是:31*2=62
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。
Input
程序的输入共有两行:
第一行共有2个自然数N,K(6≤N≤40,1≤K≤6)
第二行是一个长度为N的数字串。
Output
相对于输入,应输出所求得的最大乘积(一个自然数)。
Sample Input
4 2
1231
Sample Output
62
题
目
大
意
:
{\color{Red}题目大意:}
题 目 大 意 :
有
一
个
长
度
为
n
的
数
字
字
符
串
,
要
求
插
入
k
个
加
号
{\color{Red}有一个长度为n的数字字符串,要求插入k个\color{Cyan}加\color{Red}号}
有 一 个 长 度 为 n 的 数 字 字 符 串 , 要 求 插 入 k 个 加 号
(
不
能
在
最
前
面
和
最
后
面
)
,
求
结
果
最
大
是
多
少
{\color{Red}(不能在最前面和最后面),求结果最大是多少}
( 不 能 在 最 前 面 和 最 后 面 ) , 求 结 果 最 大 是 多 少
解题方法:
同上,代码就是改一下范围,把加号改乘号,就可以AC
#include <cstdio>
#include <iostream>
using namespace std;
int f[ 8 ] [ 42 ] , s[ 42 ] [ 42 ] , d[ 42 ] , n, m;
int main ( )
{
scanf ( "%d%d" , & n, & m) ;
getchar ( ) ;
for ( int i= 1 ; i<= n; i++ )
{
d[ i] = getchar ( ) - 48 ;
f[ i] [ 0 ] = f[ i- 1 ] [ 0 ] * 10 + d[ i] ;
}
for ( int i= 1 ; i<= n; i++ )
{
s[ i] [ i] = d[ i] ;
for ( int j= i+ 1 ; j<= n; j++ )
s[ i] [ j] = s[ i] [ j- 1 ] * 10 + d[ j] ;
}
for ( int k= 1 ; k<= m; k++ )
for ( int i= k+ 1 ; i<= n- m+ k; i++ )
for ( int j= k; j< i; j++ )
f[ i] [ k] = max ( f[ i] [ k] , f[ j] [ k- 1 ] * s[ j+ 1 ] [ i] ) ;
printf ( "%d" , f[ n] [ m] ) ;
}