背包问题与dp得到我的答案错误 import java.io.*; 导入java.util.*; 公共班机{ 公共静态void main(字符串[]args)引发异常{ 扫描仪sc=新的扫描仪(System.in); int n=sc.nextInt(); int[]val=新的int[n]; int[]权重=新int[n]; 对于(int i=0;i=0){ withCurrentItem=getMaxVal(val,wt,cap-wt[索引],索引+1,valStored+val[索引],dp); } int without currentItem=getMaxVal(val、wt、cap、索引+1、valStored、dp); dp[index][cap]=数学最大值(无当前项,有当前项); 返回Math.max(withoutCurrentItem,withCurrentItem); } }
在这个0/1背包问题中,如果我在没有dp的情况下使用相同的代码,那么它工作得很好,并且我的所有测试用例都通过了。但是如果我真的喜欢这种方式,我的一些测试用例就会失败。这里我做错了什么,请帮我解决。动态编程的思想如下:背包问题与dp得到我的答案错误 import java.io.*; 导入java.util.*; 公共班机{ 公共静态void main(字符串[]args)引发异常{ 扫描仪sc=新的扫描仪(System.in); int n=sc.nextInt(); int[]val=新的int[n]; int[]权重=新int[n]; 对于(int i=0;i=0){ withCurrentItem=getMaxVal(val,wt,cap-wt[索引],索引+1,valStored+val[索引],dp); } int without currentItem=getMaxVal(val、wt、cap、索引+1、valStored、dp); dp[index][cap]=数学最大值(无当前项,有当前项); 返回Math.max(withoutCurrentItem,withCurrentItem); } },java,algorithm,data-structures,knapsack-problem,Java,Algorithm,Data Structures,Knapsack Problem,在这个0/1背包问题中,如果我在没有dp的情况下使用相同的代码,那么它工作得很好,并且我的所有测试用例都通过了。但是如果我真的喜欢这种方式,我的一些测试用例就会失败。这里我做错了什么,请帮我解决。动态编程的思想如下:函数接受一些参数,但其输出仅取决于特定参数(如果这些参数相同,则输出总是相同的)因此,我们不会多次计算答案,因为这些参数是相同的,我们知道输出 动态编程的问题在于,您假设getMaxVal的输出仅取决于cap和index,但事实上,它也取决于valStored。但是您检查cap和in
函数接受一些参数,但其输出仅取决于特定参数(如果这些参数相同,则输出总是相同的)因此,我们不会多次计算答案,因为这些参数是相同的,我们知道输出
动态编程的问题在于,您假设getMaxVal
的输出仅取决于cap
和index
,但事实上,它也取决于valStored
。但是您检查cap
和index
并假设输出是相同的,这是错误的
一种可能的解决方案是,您可以扩展备忘录并包括valStored
,但这会增加复杂性
另一种可能的解决方案(我建议)是,您可以更改函数,使其不依赖于valStored
如何在将来发现此类错误
我是如何解决您的问题的:我实现了with dp
和without dp
函数,创建了随机输入并反复测试了这两个函数,并比较了它们的输出。当出现问题时,我打印输入并继续进一步调查。我这样说是因为您可以始终按照这些步骤自己调试代码
下面是代码(请注意,一些输入,cap
和index
是相同的,但输出是不同的)
import java.util.*;
公共班机{
静态数组列表参数;
公共静态void main(字符串[]args){
参数=新的ArrayList();
随机r=新随机(0);
int[]val;
int[]重量;
int n;
int[]dp;
用于(整数计数器=0;计数器<1000;计数器++){
System.out.println(“测试用例:+计数器”);
参数。清除();
n=r.nextInt(5)+5;
val=新整数[n];
权重=新整数[n];
对于(int i=0;i=val.length){
参数。添加(“cap:+cap+”、\t索引:+index+”、\tvalStored:+valStored+”、\t返回值:+valStored);
返回已存储的数据;
}
int with currentItem=0;
如果(上限-权重[指数]>=0){
withCurrentItem=getMaxVal(val,wt,cap-wt[index],index+1,valStored+val[index]);
}
int without currentItem=getMaxVal(val、wt、cap、索引+1、valStored);
参数.add(“cap:+cap+”,\tindex:+index+”,\tvalStored:+valStored+”,\treturn值:+Math.max(无当前项,有当前项));
返回Math.max(withoutCurrentItem,withCurrentItem);
}
公共静态int getMaxValDP(int[]val,int[]wt,int cap,int index,int valStored,int[]dp){
如果(上限==0 | |索引>=val.length){
返回已存储的数据;
}
如果(dp[指数][上限]!=0){
返回dp[指数][上限];
}
int with currentItem=0;
如果(上限-权重[指数]>=0){
withCurrentItem=getMaxValDP(val,wt,cap-wt[index],index+1,valStored+val[index],dp);
}
不带CurrentItem的int=getMaxValDP(val、wt、cap、索引+1、valStored、dp);
dp[index][cap]=数学最大值(无当前项,有当前项);
返回Math.max(withoutCurrentItem,withCurrentItem);
}
}
我建议卸下扫描仪并对一些故障数据进行硬编码。你做了什么努力来调试这个?描述你的总体逻辑/方法是个好主意。
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [] val = new int[n];
int [] weight = new int[n];
for(int i =0;i<n;i++){
val[i] = sc.nextInt();
}
for(int i =0;i<n;i++){
weight[i] = sc.nextInt();
}
int cap = sc.nextInt();
int [][]dp = new int[n+1][cap+1];
System.out.println(getMaxVal(val, weight, cap, 0, 0, dp));
}
public static int getMaxVal(int []val, int []wt, int cap, int index, int valStored, int [][]dp){
if(cap == 0 || index >= val.length){
return valStored;
}
if(dp[index][cap] != 0) {
return dp[index][cap];
}
int n = val.length;
int withCurrentItem = 0;
int inittalMaxValue = 0;
if(cap - wt[index] >=0){
withCurrentItem = getMaxVal(val, wt, cap - wt[index], index+1, valStored+val[index], dp);
}
int withoutCurrentItem = getMaxVal(val, wt, cap, index+1, valStored, dp);
dp[index][cap] = Math.max(withoutCurrentItem, withCurrentItem);
return Math.max(withoutCurrentItem, withCurrentItem);
}
}
import java.util.*;
public class Main {
static ArrayList<String> parameters;
public static void main(String[] args) {
parameters = new ArrayList<>();
Random r = new Random(0);
int[] val;
int[] weight;
int n;
int[][] dp;
for (int counter = 0; counter < 1000; counter++) {
System.out.println("Test Case: " + counter);
parameters.clear();
n = r.nextInt(5) + 5;
val = new int[n];
weight = new int[n];
for (int i = 0; i < n; i++) {
val[i] = r.nextInt(9) + 1;
}
for (int i = 0; i < n; i++) {
weight[i] = r.nextInt(9) + 1;
}
int cap = r.nextInt(90) + 10;
dp = new int[n + 1][cap + 1];
int withDP = getMaxValDP(val, weight, cap, 0, 0, dp);
int withoutDP = getMaxVal(val, weight, cap, 0, 0);
if (withDP != withoutDP) {
System.out.println("With DP: " + withDP);
System.out.println("Without DP: " + withoutDP);
System.out.println("input:");
System.out.println("n = " + n);
System.out.println("cap = " + cap);
System.out.print("val: ");
for (int i: val) {
System.out.print(i + ", ");
}
System.out.println();
System.out.print("weight: ");
for (int i: weight) {
System.out.print(i + ", ");
}
System.out.println();
Collections.sort(parameters);
for (String s: parameters){
System.out.println(s);
}
break;
}
}
}
public static int getMaxVal(int []val, int []wt, int cap, int index, int valStored){
if(cap == 0 || index >= val.length){
parameters.add("cap: " + cap + ",\tindex: " + index + ",\tvalStored: " + valStored + ",\treturn value: " + valStored);
return valStored;
}
int withCurrentItem = 0;
if(cap - wt[index] >=0){
withCurrentItem = getMaxVal(val, wt, cap - wt[index], index+1, valStored+val[index]);
}
int withoutCurrentItem = getMaxVal(val, wt, cap, index+1, valStored);
parameters.add("cap: " + cap + ",\tindex: " + index + ",\tvalStored: " + valStored + ",\treturn value: " + Math.max(withoutCurrentItem, withCurrentItem));
return Math.max(withoutCurrentItem, withCurrentItem);
}
public static int getMaxValDP(int []val, int []wt, int cap, int index, int valStored, int [][]dp){
if(cap == 0 || index >= val.length){
return valStored;
}
if(dp[index][cap] != 0) {
return dp[index][cap];
}
int withCurrentItem = 0;
if(cap - wt[index] >=0){
withCurrentItem = getMaxValDP(val, wt, cap - wt[index], index+1, valStored+val[index], dp);
}
int withoutCurrentItem = getMaxValDP(val, wt, cap, index+1, valStored, dp);
dp[index][cap] = Math.max(withoutCurrentItem, withCurrentItem);
return Math.max(withoutCurrentItem, withCurrentItem);
}
}