一、记忆化递归
(1)递归
将从1-n找V的最小值,分解为2-n找 V 或 V-arr[1] 的最小值
注:arr记录了每个物品的价值,V / V-arr[1] 对应选/不选物品1的两种情况
(2)记忆
用数组store[ ]记录 start-n中可以使重量减小的最大值,即 capacity(重量)减 min。
注:不能直接记录min 因为每次从strat开始时的capacity都不同,所以只能记录可以使重量减小的最大值(最大值对应else中的if判断)。当然重量不能减小到0,所以使用时还有个大小判断(对应第一个if
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int V, n;
int arr[40] = { 0 };
int store[20005] = { 0 };
int func(int start, int capacity);
int findmin(int x, int y);
int main()
{
scanf("%d %d", &V, &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &arr[i]);
}
for (int i = 1; i < 20005; i++)
{
store[i] = -1;
}
printf("%d", func(1, V));
return 0;
}
int func(int start,int capacity)
{
if (store[start] != -1&&capacity-store[start]>=0)
{
return capacity-store[start];
}
if (start == n)
{
if (capacity - arr[n] < 0)
{
return capacity;
}
else
{
return capacity - arr[n];
}
}
else
{
int min = findmin(func(start + 1, capacity - arr[start]), func(start + 1, capacity));
if(capacity-min<store[start]||store[start]==-1)
store[start] = capacity-min;
return min;
}
}
int findmin(int x, int y)
{
if (x < 0)
{
return y;
}
if (y < 0)
{
return x;
}
if (x < y)
{
return x;
}
else
{
return y;
}
}
后来发现其实可以把问题转换为寻找能装的最大重量,并把重量等同于01背包的价值,这样直接就用背包解决就好了,更简单
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int V, n;
int arr[40] = { 0 };
int store[20005] = { 0 };
int main()
{
scanf("%d %d", &V, &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &arr[i]);
}
for (int i = 1; i <= n; i++)
{
for (int j = V; j >= arr[i]; j--)
{
store[j] = findmax(store[j],store[j-arr[i]]+arr[i]);
}
}
printf("%d", V - store[V]);
return 0;
}
int findmax(int x, int y)
{
if (x > y)
{
return x;
}
else
{
return y;
}
}