package 揹包问题之多重揹包;
/*
* 有编号分别为a,b,c的三件物品,它们的重量分别是1,2,2,它们的价值分别是6,10,20,
* 他们的数目分别是10,5,2,
* 现在给你个承重为 8 的揹包,如何让揹包里装入的物品具有最大的价值总和
*/
public class DongtaiGuihua {
public static void main(String[] args) {
int[] weight = {1,2,2};
int[] value = {6,10,20};
int[] num = {10,5,2};
int[][] f = getMaxValue(weight,value,num,8,3);
System.out.println();
System.out.println("======================");
}
public static int[][] getMaxValue(int[] weight, int[] value,int[] num,int maxWeight,int n){
int[][] f = new int[n][maxWeight+1];
for(int i=0;i<n;i++){
f[i][0] = 0; //列为0的什么都装不了
}
//初始化第一行 代表着最大装多少
for(int j=1;j<=maxWeight;j++){
int count = Math.min(num[0], j/weight[0]);
f[0][j] = (j<weight[0])?0:count*value[0];
}
for(int i=1;i<n;i++){
for(int j=1;j<=maxWeight;j++){
if(j>=weight[i]){
//这里有差距
int count = Math.min(num[i], j/weight[i]);
f[i][j] = f[i-1][j];
for(int k=1;k<=count;k++){
int temp = f[i-1][j-weight[i]*k] + k*value[i];
if(temp >= f[i][j]){
f[i][j] = temp;
}
}
}
else{
f[i][j] = f[i-1][j];
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<=maxWeight;j++)
System.out.print(f[i][j]+" ");
System.out.println();
}
//判断路径
int[] path = new int[n];
int k = n-1;
int j=maxWeight;
while(k>0){
int count = Math.min(num[k], j/weight[k]);
if(j-weight[k]<0){
}
else {
//这里不同
for(int jishu=count;jishu>0;jishu--)
{
if(f[k][j] == (f[k-1][j-weight[k]*jishu]+jishu*value[k]))
{
path[k] = jishu;
j = j - jishu*weight[k];
break;
}
}
}
k--;
}
//
path[0] = f[0][j]/value[0];
for(int i = 0; i < n; i++)
System.out.print(path[i]+" ");
return f;
}
}
package 揹包问题之重量价值承重是否选择;
//二维数组 https://blog.csdn.net/na_beginning/article/details/62884939
public class DongTaiGuiHua {
public static void main(String[] args) {
int[] weight = {2,1,3,2};
int[] value = {12,10,20,15};
int[][] f = getMaxValue(weight,value,8,4);
System.out.println("======================");
int[] weight1 = {2,2,6,5,4};
int[] value1 = {6,3,5,4,6};
int[][] f1 = getMaxValue(weight1,value1,10,5);
}
//n件物品 0~n-1
public static int[][] getMaxValue(int[] weight, int[] value,int maxWeight,int n){
int[][] f = new int[n][maxWeight+1];
for(int i=0;i<n;i++){
f[i][0] = 0; //列为0的什么都装不了
}
//初始化第一行
for(int j=1;j<=maxWeight;j++){
f[0][j] = (j<weight[0])?0:value[0];
}
for(int i=1;i<n;i++){
for(int j=1;j<=maxWeight;j++){
if(j>=weight[i]){
f[i][j] = (f[i-1][j]>(value[i]+f[i-1][j-weight[i]]))?f[i-1][j]:(value[i]+f[i-1][j-weight[i]]);
}
else{
f[i][j] = f[i-1][j];
}
}
}
for(int i = 0; i < n; i++)
{
for(int j=0;j<=maxWeight;j++)
System.out.print(f[i][j]+" ");
System.out.println();
}
//判断路径
int[] path = new int[n];
int k = n-1;
int j=maxWeight;
while(k>0){
if(j-weight[k]<0){
}
else if(f[k][j] == (f[k-1][j-weight[k]]+value[k])){
path[k] = 1;
j = j - weight[k];
}
k--;
}
if(f[0][j]>0)
{
path[0] = 1;
}
for(int i = 0; i < n; i++)
System.out.print(path[i]+" ");
return f;
}
}
package 完全揹包问题之重量价值数量无限;
public class DongtaiGuihua {
public static void main(String[] args) {
int[] weight = {2,3,4,7};
int[] value = {1,3,5,9};
int[][] f = getMaxValue(weight,value,10,4);
System.out.println();
System.out.println("======================");
}
//n件物品 0~n-1
public static int[][] getMaxValue(int[] weight, int[] value,int maxWeight,int n){
int[][] f = new int[n][maxWeight+1];
for(int i=0;i<n;i++){
f[i][0] = 0; //列为0的什么都装不了
}
//初始化第一行 代表着最大装多少
for(int j=1;j<=maxWeight;j++){
f[0][j] = (j<weight[0])?0:(j/weight[0])*value[0];
}
for(int i=1;i<n;i++){
for(int j=1;j<=maxWeight;j++){
if(j>=weight[i]){
//这里与0 1 揹包有差距
f[i][j] = (f[i-1][j]>(value[i]+f[i][j-weight[i]]))?f[i-1][j]:(value[i]+f[i][j-weight[i]]);
}
else{
f[i][j] = f[i-1][j];
}
}
}
for(int i = 0; i < n; i++)
{
for(int j=0;j<=maxWeight;j++)
System.out.print(f[i][j]+" ");
System.out.println();
}
//判断路径
int[] path = new int[n];
int k = n-1;
int j=maxWeight;
while(k>0){
if(j-weight[k]<0){
}
else if(f[k][j] == (f[k][j-weight[k]]+value[k])){
//这里不同
path[k]++;
j = j - weight[k];
}
k--;
}
//
path[0] = f[0][j]/value[0];
for(int i = 0; i < n; i++)
System.out.print(path[i]+" ");
return f;
}
}