我在Java中做背包,我们只使用权重而没有价值。重量限制是1000.我们从键盘扫描5个重量,我们使用。 扭曲的是,你可以实际超过1000,从壁橱到1000.所以在一个场景中,我们有2个可能的重量990和1010,并且程序被调整以选择更高的一个。 扫描的数字永远不会高于1000。
package kapsackidone;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.*;
public class Kapsack {
public static void main(String[] args) throws Exception {
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int [] wt=new int[5];
int W = 1000;
System.out.println("Enter Weight 5 weights");
for(int i=0; i<5; i++)
{
wt[i]=Integer.parseInt(reader.readLine());
}
System.out.println(knapsack(wt, W));
}
public static int knapsack(int wt[], int W) {
int N = wt.length;
int[][] V = new int[N + 1][W + 1];
for (int col = 0; col <= W; col++) {
V[0][col] = 0;
}
for (int row = 0; row <= N; row++) {
V[row][0] = 0;
}
for (int item=1;item<=N;item++){
for (int weight=1;weight<=W;weight++){
if(wt[item-1] > weight)
{
V[item][weight] = V[item-1][weight];
}
else if((weight - V[item-1][weight]) < (weight - (V[item-1][weight - wt[item-1]] + wt[item-1])))
{
V[item][weight] = V[item-1][weight];
}
else
{
V[item][weight] = V[item-1][weight - wt[item-1]] + wt[item-1];
}
}
}
return V[N][W];
}
}
我真的在努力完成这项工作。 在你不要求它不做作业之前,我将成为由开发人员组成的新一群人的项目经理,所以我只是想学习一些java,这样我就能理解他们所做的一些事情,即使我怀疑我能够帮助编码。
答案 0 :(得分:2)
我会跑两次。
在第一次运行中找到&#34; classic&#34;最佳重量小于1000的溶液。
在第二次运行中,将最大值1000增加到基于先前解决方案所允许的最大可能值。
不要担心&#34;它慢两倍&#34;将复杂性乘以常数不会改变复杂性,这是背包问题中的重要事项。
如果您的代码正常运行,那么您可以计算出最佳解决方案
System.out.println(knapsack(wt,2*W - knapsack(wt, W));
或者你可以这样写它以更清楚发生了什么(它与上面的那一行完全相同)
int bestClassicSolution = knapsack(wt, W);
int differenceAgainstMaxWeight = W - bestClassicSolution;
int newMaxWeight = W + differenceAgainstMaxWeight;
int bestSolution = knapsack(wt, newMaxWeight);
System.out.println(bestSolution);
编辑:上述解决方案适用于此条件select as big solution as possible, but it must not differ from 1000 more than "below 1000" best solution
。 OP实际上想要一些不同的东西 - &#34;限制&#34;停留,但它应该是最接近1000,但尽可能高。
因此,真正的解决方案是创建反向背包方法,它将找到具有最小值的解决方案BUT必须大于&#34; min&#34;变量
public static void main(String[] args) throws Exception {
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int [] wt=new int[5];
int W = 1000;
System.out.println("Enter Weight 5 weights");
for(int i=0; i<5; i++)
{
wt[i]=Integer.parseInt(reader.readLine());
}
int bestClassicSolution = knapsack(wt, W);
int differenceAgainstMaxWeight = W - bestClassicSolution;
int newMaxWeight = W + differenceAgainstMaxWeight;
int bestMaxSolution = reversedKnapsack(wt, newMaxWeight, W);
int differenceAgainstWeightAboveW = W - bestMaxSolution;
if (differenceAgainstWeightAboveW <= differenceAgainstMaxWeight){
System.out.println(bestMaxSolution);
} else {
System.out.println(bestClassicSolution);
}
}
public static int reversedKnapsack(int wt[], int W, int min) {
//similar to knapsack method, but the solution must be as small as possible and must be bigger than min variable
}
答案 1 :(得分:0)
维基百科的逐字记录 - Subset sum problem。
使用动态编程可以在伪多项式时间内解决问题。假设序列是
,则将布尔值函数
x1, ..., xN
我们希望确定是否存在总和为零的非空子集。如果Q(i, s)
定义为值(true或false)“x1,...,xi的非空子集总和为s”。 因此,问题的解决方案“给定一组整数,是否存在非空子集,其总和为零?”是Q(N,0)的值。
设A是负值之和,B是正值之和。显然,Q(i,s)=假,如果s&lt; A或s> B.因此,不需要存储或计算这些值。
创建一个数组,以保持值Q(i,s)为1≤i≤N且A≤s≤B。
现在可以使用简单的递归填充数组。最初,对于A≤s≤B,设置
Q(1,s):=(x1 == s) 其中==是一个布尔函数,如果x1等于s则返回true,否则返回false。
然后,对于i = 2,...,N,设置
Q(i,s):= Q(i - 1,s)或(xi == s)或Q(i - 1,s - xi),A≤s≤B。
在计算Q的值后,我们可以遍历它们,并获取最接近限制的真值。
至于S的值,我们需要给出给我们的权重之和。
答案 2 :(得分:0)
经典的背包问题在Wikipedia article中讨论过;经典问题的动态规划公式可以适应以下问题。
根据权重w_1,...,w_n
和目标容量W
,找到总权重最小但大于W
的项目的子集。
为了避免病态情况,我们假设权重之和大于W
,否则没有解决方案。设W_MAX
表示所有权重的总和。
对于动态编程公式,请
m[i,j] for each i in 0,...,n and j in 0,...,W_MAX
表示通过丢弃W
的权重,总权重0,...,i
,可以获得的最小权重大于j
。
我们获得
m[0,j] = W_MAX for each j in 0,...n
并获得递归关系
m[i,j] = min {
m[i-1, i ], // corresponds to keeping weight i
m[i-1, j - w[i]] - w[i] // corresponds to discarding weight i
}
可以通过迭代i=0,...,n
和j=0,...,W_MAX
来实施评估;必须假定在m
之外的W_MAX
屈服于string clean = Regex.Replace(test, @"[^0-9a-zA-Z./ \w]+", "").Trim();
。与经典的背包问题类似,可以通过backtracking找到要丢弃的实际物品集。
最后,给定的实例可以优化两次;首先使用上面的算法,然后使用经典的背包算法。
答案 3 :(得分:0)
我首先将这个问题作为一个经典的背包问题来评估value[i] = weight[i] ;
,其中i
是第i项,最大权重是给定的max_wt( 1000 kg)和item []是一个数组,其中包含按重量升序排列的项目。
让这个问题的答案是x,比如说990公斤,现在我会算出差异'd' ,d = max_wt - x ;
迭代item []直到item [i]超过d:
int i = 0 ;
while(item[i] < d )
i++;
,最后将超过'd'的第一项添加到您通过经典背包问题得到的答案中:
answer = dp[n-1][w-1] + item[i] \\dp[n-1][w-1] is the answer of the classical
\\knapsack problem