最大K乘积问题-(动态规划(JAVA),递归思想(C))

题目描述:设I是一个n位十进制整数。如果将I分割为k段,则可得到k个整数。这k个整数的乘积称为I的一个k乘积。试设计一个算法,对于给定的I和k,求出I的最大k乘积。
1.递归思想
代码如下:

#include<stdio.h>
#include<stdlib.h>
#define max 100

//用来求分割a后的前面部分,例如123,分割后1和23,z赋1;与下文对应
int M(int *b, int t,int m)
{
	int z = 0;
	for (int i = m; i > m-t; i--)
	{
		z += b[i];
		z = z * 10;
	}
	return z / 10;
}

int rel = 0;
int Divide(int n, int k,int a)
{
	int b[max],sum;//存储整数的每一位
	if (k == 1)//当分割成一段时,即其本身
		return a;
	else
	{
		//用数组存储整数的每一位
		for (int i = 1; i <= n; i++)
		{
			b[i] = a % 10;
			a = a / 10;
		}
		for (int i = 1; i <= n - k + 1;i++)
		{
			a = 0;//防止循环时a进行累加,每进行一次循环对a重置
			//分割后剩下的数,例如:123,一次循环后,1和23,将a赋23,进行递归
			//因为a=123,在数组中是按321存储,所以,重新赋a值时从数组尾开始
			for (int j = n-i; j >= 1 ; j--)
			{
				a += b[j];
				a = a * 10;
			}
			//上述a值是实际十倍,230,所以递归时/10,sum为每次分割的乘积
			sum = M(b,i,n) * Divide(n - 1, k - 1, a / 10);
			if (rel < sum)//rel存储不同分割方法,乘积最大值
				rel = sum;
		}
		return rel;
	}
	
}

int main()
{
	int n, k, a;//n为输入整数位数,k为分割的段数,a为整数
	printf("请输入整数位数: ");
	scanf_s("%d", &n);
	printf("请输入划分段数: ");
	scanf_s("%d", &k);
	printf("请输入%d位整数:", n);
	scanf_s("%d", &a);
	printf("%d\n", Divide(n, k, a));
	system("PAUSE");
	return 0;
}

输入输出示例:
在这里插入图片描述
2.补充一下动态规划解法

package 算法设计与分析;

import java.util.Scanner;

public class zuidaKji {
	public static void main(String[] args){
        int n, k;
        int[][] m = new int[20][20];
        String num = new String();
        Scanner reader = new Scanner(System.in);

        System.out.print("输入n的值:");
        n = reader.nextInt();
        System.out.print("输入k的值:");
        k = reader.nextInt();
        System.out.print("输入要进行分段的十进制n位整数:");
        num = reader.next();
        zuidaKji.solve(num, m, n, k);
        System.out.println("最大k乘积为:" + m[n][k]);
        reader.close();
    }

    public static void solve(String num, int m[][], int n, int k){
        int max, flag;
        m[1][1] = num.charAt(0)-'0';  
        for(int i = 2; i <= n; i++)
            m[i][1] = m[i-1][1] * 10 + num.charAt(i-1) - '0';       //初始化第一列  
        for(int j = 2; j <= k; j++){                                //按列进行初始化   
            max = -1;  
            for(int i = 1; i <= n; i++){  
                if(j > i)  
                    m[i][j] = 0;  
                else{  
                    for(int l = j-1; l <= i-1; l++){  
                        flag = m[l][j-1] * StrtoInt(num, l+1, i);  
                        if(flag > max)  
                        max = flag;  
                    }  
                    m[i][j] = max;  
                }  
            }  
        }
    }
    //字符串转换为整型函数
    public static int StrtoInt(String str, int i, int j){
        int sum = 0;
        while(i <= j){  
            sum = sum*10 + str.charAt(i-1) - '0'; 
            i++;
        }
        return sum;  
    }
}

为了表达更清楚,增加一些不必要代码,可自行优化
学习中,欢迎交流,指导

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值