Problem Description
There is a box with a capacity of V (positive integer, 0≤V≤20000) and n items (0<n≤30, each item has a volume (positive integer).
It is required to take any number of n items and put them into the box to minimize the remaining space of the box.
Input format
1 integer, indicating the capacity of the box
1 integer, indicating that there are n items
The next n lines represent the respective volumes of the n items.
Output format
1 integer, indicating the remaining space of the box.
Input and output example
Input
24
6
8
3
12
7
9
7
Output
0
Thought analysis
It's actually a backpack problem. But while doing it, I came up with a new idea.
Let dp[i] = true
denote that volume i can be made up of several boxes. We find the minimum remaining space of the box to find the first i that satisfies dp[i] = true.
For each box i, traverse all volumes j, if dp[j] = true, it means that this volume has been made up before, then dp [ja[i]] is also true.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
bool dp[20020];
int n, v;
scanf("%d",&v);
scanf("%d",&n);
int arr[50];
memset(dp,0,sizeof(dp));
dp[v] = 1;
for(int i = 0;i < n;i++) scanf("%d",&arr[i]);
for(int i = 0;i < n;i++)
{
for(int j = 0;j <= v;j++)
{
if(dp[j] && j-arr[i] >= 0) dp[j-arr[i]] = 1;
}
}
for(int i = 0;i <= v;i++)
{
if(dp[i])
{
printf("%d\n",i);
break;
}
}
return 0;
}
The second is the normal 01 knapsack problem.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
//dp[i][j]表示前i物品,箱子容量为j时,箱子的最大价值(体积)
// dp[i][j] = max (dp[i-1][j], dp[i-1][j-a[i]]+a[i])
int main()
{
int v, n;
int dp[20020];
int arr[50];
memset(dp,0,sizeof(dp));
scanf("%d%d",&v,&n);
for(int i = 0;i < n;i++) scanf("%d",&arr[i]);
for(int i = 0;i < n;i++)
{
for(int j = v;j >= 0;j--)
{
if(j >= arr[i])
dp[j] = max(dp[j], dp[j-arr[i]]+arr[i]);
}
}
printf("%d\n",v-dp[v]);
return 0;
}