【问题描述】
设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),即分成一段的时候就是它本身