11090最大m段乘积和最小m段和-动态规划

来源:互联网 发布:linux内核架构 编辑:程序博客网 时间:2024/06/05 06:22

题目:

11090 最大m段乘积和最小m段和(必做)

时间限制:1000MS  内存限制:65535K
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC;VC;JAVA

Description

一个n位十进制整数S,若将S划分为m个段,则可以得到m个整数。
(1)这m个整数的乘积称为S的一个“m段乘积”,对于给定的S和m,求S的最大m段乘积。
(2)这m个整数的和称为S的一个“m段和”,对于给定的S和m,求S的最小m段和。




输入格式

输入:三个整数,n,m,S。
第一个n表示S的位数,第二个m表示分割的段数,第三个数为需要被分段的n位十进制数S。
n、m和S三个数中间空格相连,这里1<=m<=n,n<=10,即S、S的最大m段乘积、S的最小m段和这三个
数都用int型即可,虽然输出的数可能很大,但这里32位整数够了,测试数据没有超过32位整数,即
无需考虑多位的高精度数。

例如,十进制数3456的“最大3段乘积”为1020。因为3456划分3个段有如下情形:
3*4*56=672,3*45*6=810,34*5*6=1020。
3456的“最小3段和”为45,因为3+4+56=63,3+45+6=54,34+5+6=45。



输出格式

输出:
计算出的最大m段乘积和最小m段和,中间空格相连。

这里约定:
(1)若有多种分段方法使得最大m段乘积相等且都最大,则优先输出靠左的段更短小的这种方式。
   比如输入3 2 111,这里最大m段乘积的乘法表达式为:1*11=11,而不要输出11*1=11
(2)若分出的某段数字有0开头的,不输出0。
   比如输入5 3 20001,这里输出:2*0*1=0,(其实代表着:2*0*001,这里001,只写1即可)
(3)若只分一个段,表达式也就写1个段的数等于某个数。
   比如输入2 1 12,输出:12=12
(4)最小m段和的加法表达式也同样满足前面的约定(1)(2)(3)。



输入样例

4 3 3456



输出样例

1020 45

代码:

#include "stdafx.h"#include<iostream>using namespace std;int array_s[11];//存储分割后的数字int n, m, s;//定义全局变量N,M,Sinline int w(int _h, int _t);//计算起始h到t位的数字,相当于合并分割后的数字inline void divide(int _s,int _n);//分割s的每个数字inline int f(int _i, int _j);//最大m段乘积inline int t(int _i, int _j);//最小m段和int main(){cin >> n >> m >> s;divide(s, n);cout << f(n, m) << endl;cout << t(n, m) << endl;    return 0;}inline int f(int _i, int _j) {int max = 0;if (_j == 1) {max = w(1, _i);}else if(_j >= 2){for (int k = _j - 1; k <= _i - 1; k++) {max = f(k, _j - 1) * w(k + 1, _i - k);}}return max;}inline int t(int _i, int _j) {int min;if (_j == 1) {min = w(1, _i);}else if (_j >= 2) {for (int k = _j - 1; k <= _i - 1;k++) {min = t(k, _j - 1) + w(k + 1, _i - k);}}return min;}inline int w(int _h, int _t) {int temp = 0;for (int i = _h; i < _h + _t; i++) {temp *= 10;temp += array_s[i];}return temp;}inline void  divide(int _s,int _n) {for (int i = _n; i > 0; i--) {array_s[i] = _s % 10;_s = _s / 10;}}


0 0