现在有一个长度为length=m的木头按以下切割的方法 给出n个长度为,len1,len2,len3.....leni<m 使得x1len1+x2len2+x3*len3.....最大并且<=m,其中x1,x2,x3.....xi的数量有可能都不相同
求出x1,x2,x3....xi
并且切割的时候会有损失sq,sq也手动输入。例如切割一段就有sq长度的损失
输入要求:
m n sq
接下来输入n个小余m的整数
len1,len2,len3......lenn
输出一共(n+1)行
x1=?
x2=?
....
xn=?
??(这行为切割后剩余的木头长度)
注: 1、但是要注意的是,例如木头长度length为5,要切割成len1=2,损失为sq=1。只需要切一刀,损失为1,就可以得到两个为2的木材
2、以上数据都为正整数
遇到问题比如一个例子:length=381,sq=3,n=3
len1=66,len2=87,len3=153
最优的应该是(66+3)+(66+3)+(87+3)+153=381 (+3是切割损失的锯缝)
这个是3个锯缝,下面C#代码会算成4个锯缝,求大佬帮忙优化一下代码,或者有好的代码可以给我借鉴借鉴。
public static void mains()
{
Console.WriteLine("请输入目标长度(例如 1000):");
int target = int.Parse(Console.ReadLine());
Console.WriteLine("请输入每次切割的损失长度(sq):");
int sq = int.Parse(Console.ReadLine());
Console.WriteLine("请输入长度的数量:");
int count = int.Parse(Console.ReadLine());
List<int> lengths = new List<int>();
for (int i = 0; i < count; i++)
{
Console.WriteLine($"请输入第 {i + 1} 个长度(<1000):");
int length = int.Parse(Console.ReadLine());
lengths.Add(length);
}
var result = FindMaxCombination(lengths, target, sq);
Console.WriteLine($"最大组合的总长度为:{result.Item1}");
Console.WriteLine($"剩余的长度为:{result.Item3}");
Console.WriteLine("对应的系数为:");
for (int i = 0; i < result.Item2.Length; i++)
{
Console.WriteLine($"x{i + 1} = {result.Item2[i]}");
}
}
static Tuple<int, int[], int> FindMaxCombination(List<int> lengths, int target, int sq = 3)
{
int[] dp = new int[target + 1];
int[] lastUsed = new int[target + 1]; // 记录达到每个值最后使用的长度索引
int[] cutCount = new int[target + 1]; // 记录达到每个值时的切割次数
for (int i = 0; i < lengths.Count; i++)
{
for (int j = lengths[i] + sq; j <= target; j++)
{
if (dp[j - (lengths[i] + sq)] + lengths[i] > dp[j])
{
dp[j] = dp[j - (lengths[i] + sq)] + lengths[i];
lastUsed[j] = i;
cutCount[j] = cutCount[j - (lengths[i] + sq)] + 1;
}
}
}
// 回溯找到使用的每个长度的次数
int[] counts = new int[lengths.Count];
int totalCuts = 0;
int currentTarget = target;
while (currentTarget > 0)
{
if (lastUsed[currentTarget] == 0 && dp[currentTarget] == 0) break; // 避免无限循环
int lengthIndex = lastUsed[currentTarget];
counts[lengthIndex]++;
totalCuts += cutCount[currentTarget] - cutCount[currentTarget - (lengths[lengthIndex] + sq)];
currentTarget -= lengths[lengthIndex] + sq;
}
int residue = target - (dp[target] + totalCuts * sq);
return Tuple.Create(dp[target], counts, residue);
}