返回目录
题目描述
一根X米长的树木,伐木工切割成不同长度的木材后进行交易,交易价格为每根木头长度的乘积。规定切割后的每根木头长度都为正整数;也可以不切割,直接拿整根树木进行交易。
请问伐木工如何尽量少的切割,才能使收益最大化?
输入描述
木材的长度(X ≤ 50)
输出描述
输出最优收益时的各个树木长度,以空格分隔,按升序排列
示例:
输入 | 10 |
---|---|
输出 | 3 3 4 |
说明 | 一根2米长的树木,伐木工不切割,为2* 1,收益最大为2 一根4米长的树木,伐木工不需要切割为2 * 2,省去切割成本,直接整根树木交易,为4 * 1,收 益最大为4 一根5米长的树木,伐木工切割为2 * 3,收益最大为6 一根10米长的树木,伐木工可以切割方式一:3,4,4,也可以切割为方式二:3,2,2,3, 但方式二伐木工多切割一次,增加切割成本却买了一样的价格,因此并不是最优收益。 |
Python算法源码
def get_max_profit(length):
# dp数组用于存储每个长度的最大乘积
dp = [0] * (length + 1)
# cutTimes数组用于存储每个长度的最佳切割次数
cut_times = [0] * (length + 1)
# lastCut数组用于存储每个长度的最后一次切割长度
last_cut = [0] * (length + 1)
# 遍历每个长度
for i in range(1, length + 1):
# 初始化dp和lastCut数组
dp[i] = last_cut[i] = i
# 遍历所有可能的切割长度
for j in range(1, i):
# 计算当前切割长度的乘积
product = dp[i - j] * j
# 如果当前乘积大于已知的最大乘积,更新最大乘积和最佳切割长度
if product > dp[i]:
last_cut[i] = j
dp[i] = product
cut_times[i] = cut_times[i - j] + 1
# 如果当前乘积等于已知的最大乘积,但切割次数更少,更新最佳切割长度和切割次数
elif product == dp[i] and cut_times[i] > cut_times[i - j] + 1:
last_cut[i] = j
cut_times[i] = cut_times[i - j] + 1
# 从最大长度开始,每次减去最佳切割长度,直到长度为0
results = []
while length > 0:
# 将最佳切割长度添加到结果的开头
results.insert(0, last_cut[length])
# 更新长度
length -= last_cut[length]
# 返回结果
return results
# 读取输入的长度
length = int(input())
# 调用get_max_profit方法计算最大利润,并将结果存储在一个列表中
results = get_max_profit(length)
# 遍历结果并打印
for i in results:
print(i, end=" ")
C语言算法源码
#include <stdio.h>
#include <stdlib.h>
// 定义函数,计算给定长度的最大乘积分割
int* get_max_profit(int length) {
// 分配内存来存储结果
int* results = (int*)malloc(length * sizeof(int));
// dp数组用于存储每个长度的最大乘积
int dp[length + 1];
// cutTimes数组用于存储每个长度的最佳切割次数
int cut_times[length + 1];
// lastCut数组用于存储每个长度的最后一次切割长度
int last_cut[length + 1];
// 遍历每个长度
for (int i = 1; i <= length; i++) {
// 初始化dp和lastCut数组
dp[i] = last_cut[i] = i;
// 遍历所有可能的切割长度
for (int j = 1; j < i; j++) {
// 计算当前切割长度的乘积
int product = dp[i - j] * j;
// 如果当前乘积大于已知的最大乘积,更新最大乘积和最佳切割长度
if (product > dp[i]) {
last_cut[i] = j;
dp[i] = product;
cut_times[i] = cut_times[i - j] + 1;
}
// 如果当前乘积等于已知的最大乘积,但切割次数更少,更新最佳切割长度和切割次数
else if (product == dp[i] && cut_times[i] > cut_times[i - j] + 1) {
last_cut[i] = j;
cut_times[i] = cut_times[i - j] + 1;
}
}
}
// 从最大长度开始,每次减去最佳切割长度,直到长度为0
int index = 0;
while (length > 0) {
// 将最佳切割长度添加到结果数组中
results[index++] = last_cut[length];
// 更新长度
length -= last_cut[length];
}
// 返回结果
return results;
}
int main() {
// 读取输入的长度
int length;
printf("Enter the length: ");
scanf("%d", &length);
// 调用get_max_profit函数计算最大利润,并将结果存储在一个数组中
int* results = get_max_profit(length);
// 打印结果
printf("Max product cutting lengths: ");
for (int i = 0; results[i] != 0; i++) {
printf("%d ", results[i]);
}
printf("\n");
// 释放动态分配的内存
free(results);
return 0;
}
Java算法源码
import java.util.Scanner;
public class Main {
// 定义函数,计算给定长度的最大乘积分割
public static int[] get_max_profit(int length) {
// dp数组用于存储每个长度的最大乘积
int[] dp = new int[length + 1];
// cutTimes数组用于存储每个长度的最佳切割次数
int[] cutTimes = new int[length + 1];
// lastCut数组用于存储每个长度的最后一次切割长度
int[] lastCut = new int[length + 1];
// 遍历每个长度
for (int i = 1; i <= length; i++) {
// 初始化dp和lastCut数组
dp[i] = lastCut[i] = i;
// 遍历所有可能的切割长度
for (int j = 1; j < i; j++) {
// 计算当前切割长度的乘积
int product = dp[i - j] * j;
// 如果当前乘积大于已知的最大乘积,更新最大乘积和最佳切割长度
if (product > dp[i]) {
lastCut[i] = j;
dp[i] = product;
cutTimes[i] = cutTimes[i - j] + 1;
}
// 如果当前乘积等于已知的最大乘积,但切割次数更少,更新最佳切割长度和切割次数
else if (product == dp[i] && cutTimes[i] > cutTimes[i - j] + 1) {
lastCut[i] = j;
cutTimes[i] = cutTimes[i - j] + 1;
}
}
}
// 创建一个列表来存储结果
int[] results = new int[length];
int index = 0;
// 从最大长度开始,每次减去最佳切割长度,直到长度为0
while (length > 0) {
// 将最佳切割长度添加到结果数组中
results[index++] = lastCut[length];
// 更新长度
length -= lastCut[length];
}
// 返回结果
return results;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入的长度
System.out.print("Enter the length: ");
int length = scanner.nextInt();
// 调用get_max_profit方法计算最大利润,并将结果存储在一个数组中
int[] results = get_max_profit(length);
// 打印结果
System.out.print("Max product cutting lengths: ");
for (int result : results) {
System.out.print(result + " ");
}
System.out.println();
}
}
3 条评论
[...]2024 C卷 100分序号题目知 识 点难易程度1密码输入检测数据结构/栈☆☆☆2分配土地几何问题☆☆☆3找座位逻辑分析☆☆☆4智能成绩表动态条件分析☆☆☆5内存冷热标记多条件排序☆☆☆6螺旋数字矩阵逻辑分析☆☆☆7围棋的气逻辑分析☆☆☆8分割平衡字符串逻辑分析☆☆☆9机器人搬砖二分法☆☆☆10转盘寿司数据结构/栈/单调栈☆☆☆11小明找位置二分法☆☆☆12提取字符串的最长合法简单数学表达式双指[...]
[...]2024 C卷 100分序号题目知 识 点难易程度1密码输入检测数据结构/栈☆☆☆2分配土地几何问题☆☆☆3找座位逻辑分析☆☆☆4智能成绩表动态条件分析☆☆☆5内存冷热标记多条件排序☆☆☆6螺旋数字矩阵逻辑分析☆☆☆7围棋的气逻辑分析☆☆☆8分割平衡字符串逻辑分析☆☆☆9机器人搬砖二分法☆☆☆10转盘寿司数据结构/栈/单调栈☆☆☆11小明找位置二分法☆☆☆12提取字符串的最长合法简单数学表达式双指[...]
[...]2024 C卷 100分序号题目知 识 点难易程度1密码输入检测数据结构/栈☆☆☆2分配土地几何问题☆☆☆3找座位逻辑分析☆☆☆4智能成绩表动态条件分析☆☆☆5内存冷热标记多条件排序☆☆☆6螺旋数字矩阵逻辑分析☆☆☆7围棋的气逻辑分析☆☆☆8分割平衡字符串逻辑分析☆☆☆9机器人搬砖二分法☆☆☆10转盘寿司数据结构/栈/单调栈☆☆☆11小明找位置二分法☆☆☆12提取字符串的最长合法简单数学表达式双指[...]