如下这个算法如何改造为避免递归函数的动态规划? public class StonePacking { private List<List<Integer>> bucketsWithStones = new ArrayList(); public static void main(String[] args) { int[] stones = {105, 45, 30, 45, 45, 5, 60, 45, 30, 30, 45, 60, 60, 45, 40, 30, 60, 30,30}; int[] buckets = {180, 240, 180, 240}; Arrays.sort(stones); int[] remainingSpace = Arrays.copyOf(buckets, buckets.length); boolean[] isPacked = new boolean[stones.length]; Arrays.fill(isPacked, false); StonePacking stonePacking = new StonePacking(); stonePacking.bucketsWithStones.add(new ArrayList<>()); stonePacking.bucketsWithStones.add(new ArrayList<>()); stonePacking.bucketsWithStones.add(new ArrayList<>()); stonePacking.bucketsWithStones.add(new ArrayList<>()); boolean canPack = stonePacking.packStones(stones, remainingSpace, isPacked, 0); if (canPack) { System.out.println("能够将所有石头放入木桶中"); System.out.println("剩余空间:"); for (int i = 0; i < buckets.length; i++) { System.out.println("木桶" + (i + 1) + ":" + remainingSpace[i] + "斤"); } } else { System.out.println("无法将所有石头放入木桶中"); } System.out.println(stonePacking.bucketsWithStones); } private boolean packStones(int[] stones, int[] remainingSpace, boolean[] isPacked, int index) { if (index == stones.length) { return true; // 所有石头都已经放置完毕 } for (int i = 0; i < remainingSpace.length; i++) { if (!isPacked[index] && stones[index] <= remainingSpace[i]) { remainingSpace[i] -= stones[index]; /*if(!this.bucketsWithStones.get(i).contains(index)){ this.bucketsWithStones.get(i).add(stones[index]); }*/ System.out.println(String.format("remainingSpace[%s]=%s,stone[%s]=%s",i, remainingSpace[i], index, stones[index])); isPacked[index] = true; if (packStones(stones, remainingSpace, isPacked, index + 1)) { return true; } remainingSpace[i] += stones[index]; isPacked[index] = false; } } return false; } }
时间: 2024-02-14 22:30:09 浏览: 148
要将这个算法改造为动态规划,你可以使用一个二维数组来表示状态转移表。每个状态表示前i个石头放进前j个木桶时的剩余容量。
下面是修改后的代码:
```java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StonePacking {
private static List<List<Integer>> bucketsWithStones = new ArrayList<>();
public static void main(String[] args) {
int[] stones = {105, 45, 30, 45, 45, 5, 60, 45, 30, 30, 45, 60, 60, 45, 40, 30, 60, 30, 30};
int[] buckets = {180, 240, 180, 240};
Arrays.sort(stones);
int[][] dp = new int[stones.length + 1][buckets.length + 1];
for (int i = stones.length - 1; i >= 0; i--) {
for (int j = buckets.length - 1; j >= 0; j--) {
dp[i][j] = dp[i + 1][j];
if (stones[i] <= buckets[j] && dp[i + 1][j + 1] + stones[i] <= buckets[j]) {
dp[i][j] = Math.max(dp[i][j], dp[i + 1][j + 1] + stones[i]);
}
}
}
boolean[] isPacked = new boolean[stones.length];
Arrays.fill(isPacked, false);
packStones(stones, buckets, dp, isPacked);
if (bucketsWithStones.size() == stones.length) {
System.out.println("能够将所有石头放入木桶中");
System.out.println("剩余空间:");
for (int i = 0; i < buckets.length; i++) {
System.out.println("木桶" + (i + 1) + ":" + (buckets[i] - dp[0][i]) + "斤");
}
} else {
System.out.println("无法将所有石头放入木桶中");
}
System.out.println(bucketsWithStones);
}
private static void packStones(int[] stones, int[] buckets, int[][] dp, boolean[] isPacked) {
int i = 0;
int j = 0;
while (i < stones.length && j < buckets.length) {
if (stones[i] <= buckets[j] && dp[i][j] == dp[i + 1][j + 1] + stones[i]) {
buckets[j] -= stones[i];
if (!bucketsWithStones.contains(j)) {
bucketsWithStones.add(j, new ArrayList<>());
}
bucketsWithStones.get(j).add(stones[i]);
isPacked[i] = true;
i++;
j++;
} else {
j++;
}
}
}
}
```
在这个修改后的代码中,我们创建了一个二维数组 `dp` 来表示状态转移表。使用动态规划的思想,我们从右下角开始填充状态转移表,计算出每个状态对应的最大剩余容量。
然后,我们使用两个指针 `i` 和 `j` 来遍历 `stones` 和 `buckets` 数组。如果 `stones[i]` 可以放入 `buckets[j]` 中并且选择放入它之后的状态比选择不放入它之后的状态更优,则我们将该石头放入木桶中,并更新剩余容量和已放入的石头。
最后,我们检查 `bucketsWithStones` 列表的长度是否与 `stones` 数组的长度相等,如果相等则说明成功将所有石头放入木桶中。
希望这次的修改能够解决问题。如果还有其他问题,请随时提问。
阅读全文