0-1背包中N个物品的最大价值总和,最多将K个物品的重量减半
给定N件物品的重量和价值以及背包的容量W。还假设最多可以将K件物品的重量更改为其原始重量的一半。任务是找到可以得到的N个物品的最大价值总和,使得背包中物品的重量总和不超过给定的容量W。
例子:
Input: W = 4, K = 1, value = [17, 20, 10, 15], weight = [4, 2, 7, 5]
Output: 37
Explanation: Change the weight of at most K items to half of the weight in a optimal way to get maximum value. Decrease the weight of first item to half and add second item weight the resultant sum of value is 37 which is maximum
Input: W = 8, K = 2, value = [17, 20, 10, 15], weight = [4, 2, 7, 5]
Output: 53
Explanation: Change the weight of the last item and first item and the add the weight the of the 2nd item, The total sum value of item will be 53.
方法:给定问题是 0 1 背包问题的变体。标志表示重量已减半的项目数。在每次递归调用时,计算并返回以下情况的最大值:
- 基本情况:如果索引超过值的长度,则返回零
- 如果 flag 等于K,则最大值 考虑2种情况:
- 如果物品的重量不超过剩余重量,则包括物品的全重
- 跳过项目
- 如果 flag 小于K,则最大值 考虑3种情况:
- 如果物品的重量不超过剩余重量,则包括物品的全重
- 如果物品的一半重量不超过剩余重量,则包括一半重量的物品
- 跳过项目
C++
// C++ Program to implement
// the above approach
#include
using namespace std;
// Function to find the maximum value
int maximum(int value[],
int weight[], int weight1,
int flag, int K, int index, int val_len)
{
// base condition
if (index >= val_len)
{
return 0;
}
// K elements already reduced
// to half of their weight
if (flag == K)
{
// Dont include item
int skip = maximum(value,
weight, weight1,
flag, K, index + 1, val_len);
int full = 0;
// If weight of the item is
// less than or equal to the
// remaining weight then include
// the item
if (weight[index] <= weight1)
{
full = value[index] + maximum(
value, weight,
weight1 - weight[index], flag,
K, index + 1, val_len);
}
// Return the maximum of
// both cases
return max(full, skip);
}
// If the weight reduction to half
// is possible
else
{
// Skip the item
int skip = maximum(
value, weight,
weight1, flag,
K, index + 1, val_len);
int full = 0;
int half = 0;
// Include item with full weight
// if weight of the item is less
// than the remaining weight
if (weight[index] <= weight1)
{
full = value[index] + maximum(
value, weight,
weight1 - weight[index],
flag, K, index + 1, val_len);
}
// Include item with half weight
// if half weight of the item is
// less than the remaining weight
if (weight[index] / 2 <= weight1)
{
half = value[index] + maximum(
value, weight,
weight1 - weight[index] / 2,
flag, K, index + 1, val_len);
}
// Return the maximum of all 3 cases
return max(full,
max(skip, half));
}
}
int main()
{
int value[] = {17, 20, 10, 15};
int weight[] = {4, 2, 7, 5};
int K = 1;
int W = 4;
int val_len = sizeof(value) / sizeof(value[0]);
cout << (maximum(value, weight, W,
0, K, 0, val_len));
return 0;
}
// This code is contributed by Potta Lokesh
Java
// Java implementation for the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to find the maximum value
static int maximum(int value[],
int weight[], int weight1,
int flag, int K, int index)
{
// base condition
if (index >= value.length) {
return 0;
}
// K elements already reduced
// to half of their weight
if (flag == K) {
// Dont include item
int skip = maximum(value,
weight, weight1,
flag, K, index + 1);
int full = 0;
// If weight of the item is
// less than or equal to the
// remaining weight then include
// the item
if (weight[index] <= weight1) {
full = value[index]
+ maximum(
value, weight,
weight1 - weight[index], flag,
K, index + 1);
}
// Return the maximum of
// both cases
return Math.max(full, skip);
}
// If the weight reduction to half
// is possible
else {
// Skip the item
int skip = maximum(
value, weight,
weight1, flag,
K, index + 1);
int full = 0;
int half = 0;
// Include item with full weight
// if weight of the item is less
// than the remaining weight
if (weight[index] <= weight1) {
full = value[index]
+ maximum(
value, weight,
weight1 - weight[index],
flag, K, index + 1);
}
// Include item with half weight
// if half weight of the item is
// less than the remaining weight
if (weight[index] / 2 <= weight1) {
half = value[index]
+ maximum(
value, weight,
weight1 - weight[index] / 2,
flag, K, index + 1);
}
// Return the maximum of all 3 cases
return Math.max(full,
Math.max(skip, half));
}
}
public static void main(String[] args)
throws Exception
{
int value[] = { 17, 20, 10, 15 };
int weight[] = { 4, 2, 7, 5 };
int K = 1;
int W = 4;
System.out.println(
maximum(value, weight, W,
0, K, 0));
}
}
Python3
# Python program for the above approach
# Function to find the maximum value
def maximum(value,
weight, weight1,
flag, K, index, val_len) :
# base condition
if (index >= val_len) :
return 0
# K elements already reduced
# to half of their weight
if (flag == K) :
# Dont include item
skip = maximum(value,
weight, weight1,
flag, K, index + 1, val_len)
full = 0
# If weight of the item is
# less than or equal to the
# remaining weight then include
# the item
if (weight[index] <= weight1) :
full = value[index] + maximum(
value, weight,
weight1 - weight[index], flag,
K, index + 1, val_len)
# Return the maximum of
# both cases
return max(full, skip)
# If the weight reduction to half
# is possible
else :
# Skip the item
skip = maximum(
value, weight,
weight1, flag,
K, index + 1, val_len)
full = 0
half = 0
# Include item with full weight
# if weight of the item is less
# than the remaining weight
if (weight[index] <= weight1) :
full = value[index] + maximum(
value, weight,
weight1 - weight[index],
flag, K, index + 1, val_len)
# Include item with half weight
# if half weight of the item is
# less than the remaining weight
if (weight[index] / 2 <= weight1) :
half = value[index] + maximum(
value, weight,
weight1 - weight[index] / 2,
flag, K, index + 1, val_len)
# Return the maximum of all 3 cases
return max(full,
max(skip, half))
# Driver Code
value = [ 17, 20, 10, 15 ]
weight = [ 4, 2, 7, 5 ]
K = 1
W = 4
val_len = len(value)
print(maximum(value, weight, W,
0, K, 0, val_len))
# This code is contributed by sanjoy_62.
C#
// C# implementation for the above approach
using System;
public class GFG {
// Function to find the maximum value
static int maximum(int []value,
int []weight, int weight1,
int flag, int K, int index)
{
// base condition
if (index >= value.Length) {
return 0;
}
// K elements already reduced
// to half of their weight
if (flag == K) {
// Dont include item
int skip = maximum(value,
weight, weight1,
flag, K, index + 1);
int full = 0;
// If weight of the item is
// less than or equal to the
// remaining weight then include
// the item
if (weight[index] <= weight1) {
full = value[index]
+ maximum(
value, weight,
weight1 - weight[index], flag,
K, index + 1);
}
// Return the maximum of
// both cases
return Math.Max(full, skip);
}
// If the weight reduction to half
// is possible
else {
// Skip the item
int skip = maximum(
value, weight,
weight1, flag,
K, index + 1);
int full = 0;
int half = 0;
// Include item with full weight
// if weight of the item is less
// than the remaining weight
if (weight[index] <= weight1) {
full = value[index]
+ maximum(
value, weight,
weight1 - weight[index],
flag, K, index + 1);
}
// Include item with half weight
// if half weight of the item is
// less than the remaining weight
if (weight[index] / 2 <= weight1) {
half = value[index]
+ maximum(
value, weight,
weight1 - weight[index] / 2,
flag, K, index + 1);
}
// Return the maximum of all 3 cases
return Math.Max(full,
Math.Max(skip, half));
}
}
// Driver code
public static void Main(String[] args)
{
int []value = { 17, 20, 10, 15 };
int []weight = { 4, 2, 7, 5 };
int K = 1;
int W = 4;
Console.WriteLine(
maximum(value, weight, W,
0, K, 0));
}
}
// This code is contributed by shikhasingrajput
Javascript
37
时间复杂度: O(3^N)
辅助空间: O(N)