最大k乘积问题----动态规划

问题

设I是一个n位十进制整数。如果将I划分为k段,则可得到k个整数。这k个整数的乘积称为I的一个k乘积。试设计一个算法,对于给定的I和k,求出I的最大k乘积。
编程任务:
对于给定的I 和k,编程计算I 的最大k 乘积。
需求输入:
输入的第1 行中有2个正整数n和k。正整数n是序列的长度;正整数k是分割的段数。接下来的一行中是一个n位十进制整数。(n<=10)
需求输出:
计算出的最大k乘积。

例如输入

4 3

1234

输出:144

分析

  设m(i,j)表示将第i~n位数划分为j段的最大乘积
  设n位的整数用字符串表示为X1X2X3...Xn
  假设n为5,整数为12345
  则m(1,3)就表示为从第一位到第五位划分为三个整数
  例如可以这样分:{1*23*45} {1*2*345} {1*234*5} {12*3*45} {12*34*5} {123*4*5}
  其中最大的就是123*4*5=2460
  a(i,j)表示将第i位到第j位化成一个整体,例如a(2,3)=23 
  m(i,j) = max{ a(i,s)*m(i+s,j-1) } 1 <= j <= n-i+1   1 <= s <= (n-i+1)-(j-1)
  上面式子表示m(i,j)可以将前面i~i+s-1位看成一个整体,后面i+s~j再划分位j-1个整数  s就是中间的切分点 
  其中边界值位:m(i,1) = a(i,n);即把i~n看成一个整体 

 代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>



//截取子字符串 
void SubStr(char *s,int start,int end,char *newStr){
	int i,j;
	for(i = start-1,j = 0; i <= end-1; i++){
		newStr[j++] = s[i];
	}
	newStr[end-start+1] = '\0';
}

//将字符串转换为整数 
int ConvertInt(char *s,int start,int end){
	SubStr(s,start,end,newStr);
	int a = atoi(newStr);
	return a;
}

void solve(int n,int k,char *num){
	//初始化 
	int m[n+1][n+1];
	for(int i = 1; i <= n; i++){
		m[i][1] = ConvertInt(num,i,n);
		for(int j = 2; j <= n; j++)
			m[i][j] = 0;
	}
	//自顶向下递归的计算 
	for(int i = n-1; i >= 1; i--){
		for(int j = 2; j <= n-i+1; j++){
			for(int s = 1; s <= (n-i+1)-(j-1); s++){
				int a = ConvertInt(num,i,i+s-1);//a(i,i+s-1); 
				int b = m[i+s][j-1];
				int c = a * b;
				if(c > m[i][j])
					m[i][j] = c;
			}
		}
	}
	printf("最大%d乘积为:%d",k,m[1][k]);
}

int main(){
	int n,k;
	scanf("%d %d",&n,&k);
	if(n > 10 || k > n) return 0;
	char num[n+1];
	int i = 0;
	getchar();//吸收回车 
	do{
		num[i] = getchar();
		++i;
	}while(i < n);
	solve(n,k,num);
	return 0;
} 

 

  • 1
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值