动态规划--最大k乘积

【问题描述】
设X是一个n位十进制整数,如果将X划分为K段,则可得到K个整数,这K个整数的乘积称为X的一个K乘积。请设计算法并编程实现,对于给定的X 和K,求出X的最大K乘积。
【输入】
X,K,n
【输出】
X的最大K乘积。
【分析】
首先,考虑分为一段的时候,最大乘积就是它本身;
从第一位开始,将整个数字分为b段,但是要考虑,如果分成的段数比位数还多,直接f[a][b]=0;如果分成的段数等于位数的话,说明是它的每一位相乘
最后,找最大值,假设将前k位分为b-1段,后面元素为Number(k+1,a),乘积就是f[k][b-1]*Number(k+1,a),比较f[a][b]和f[k][b-1]*Number(k+1,a),取最大值

【源代码】

#include<stdlib.h> 
#include<stdio.h>
//函数声明 
 int F(int i,int j);
 void Getnum(int Num,int n);
 int Number(int i,int j);
 int Max(int i,int j);
 int n;//位数 
 int getnum[20];//存储分离后的每位数字
 int num[20][20];//num[i][j]为从i到j组成的数,相当于重新排列后的数
 int Num;//要计算的数 
 int f[20][20];//将i个数据分为j段的最大乘积 
 int j;//j是要分成的段数 
 int main()
 {
 	int m,sum=1;
 	printf("请输入位数:");
 	scanf("%d",&n);
	printf("请输入要计算的数:");
 	scanf("%d",&Num);
 	Getnum(Num,n);
 	printf("请输入要分成的段数:");
	scanf("%d",&j); 
	
 	if(j==1)
	 	printf("最大k乘积是:%d",Num); //如果就分成一段的话,就是它自己 
	else
		printf("最大k乘积是:%d",F(n,j)); 
 	
 }
 
 
 int F(int i,int j)//将i个元素分为j段 
{
	int a,b;
	int k,m,sum=1;
	f[0][0]=0;
	f[n][1]=Number(1,n);
	for(a=1;a<=i;a++)//a是位数 ,从第一位开始 
	{
		for(b=2;b<=j;b++)// b是段数 ,要从两段开始 
		{
			if(a<b)//要分的段数比位数还多,不能分割
				{f[a][b]=0;
				 continue; 
			 	} 
			if(a==b)//如果分的段数等于位数的话,结果等于每一位的乘积 
				{
					for(m=1;m<=a;m++)
					{
						sum=sum*getnum[m];
					}
					f[a][b]=sum;
				}
			for(k=1;k<=a;k++)//k是断开的位数 
			{
				f[a][b]=Max(f[a][b],f[k][b-1]*Number(k+1,a));
				f[k][1]=Number(1,k);
			}
		}
	}
	return f[i][j];
 } 
 
 
 void Getnum(int Num,int n)//将数字的每一位分离并存储 
 {
 	int b=0;
	int a;
	for(a=n;a>0;a--)
	{
		b=Num%10;//求最低位 
		Num=Num/10;//位数减少一位 
		getnum[a]=b;//最终存储就是按数字顺序存储每位 
	 } 
 } 
 
 int Number(int i,int j)//还原从第i位到第j位的数字 
 {
 	int sum=0;//逐层乘10,并加上低位 
	int a;
	for(a=i;a<=j;a++)
	{
		sum=sum*10+getnum[a];
	  } 
	num[i][j] = sum;
	return sum;
  } 
int Max(int i,int j)//求最大值 
{
  	if(i>=j)
  		return i;
  	else
  		return j;
}

【实验结果】
在这里插入图片描述

【收获】
核心算法就是三个for循环,但是每位数的分离和再组合也很重要;
另外,需要在计算的时候强调f[k][1]=Number(1,k),即分成一段的时候就是它本身

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值