Input
Output
Sample
input | output |
---|---|
5 5 8 13 27 14 | 3 |
这是一个背包问题,发现背包问题自己已经忘记的差不多了,所以决定重新弄清楚。
有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。
求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
基础的是01背包问题,特点是每种物品仅有一件,可以选择放或不放。
f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大值。
f[i][v] = max{f[i-1][v],f[i-1][v-w[i]]+v[i]}
压缩为f[v] = max{f[v],f[v-w[i]]+v[i]}
将问题分解为“前i件物品放入容量为v的背包中”这个子问题,如果只考虑第i件物品放入问题,那么就
转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么文件转化为“前i-1件物品放入容量为
v的背包中”,价值为f[i-1][v];如果放第i件物品,问题就转化为“前i-1件物品放入剩下的容量为
v-w[i]的背包中”,此时能获得的最大价值就是f [i-1][v-w[i]]再加上通过放入第i件物品获得的价值v[i].
#include<iostream>
using namespace std;
#define V 1500
unsigned int f[10][V];//全局变量,自动初始化为0
unsigned int weight[10];
unsigned int value[10];
#define max(x,y) (x)>(y)?(x):(y)
int main()
{
int N,M;
cin>>N;//物品个数
cin>>M;//背包容量
for (int i=1;i<=N; i++)
{
cin>>weight[i]>>value[i];
}
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++)
{
if (weight[i]<=j)
{
f[i][j]=max(f[i-1][j],f[i-1][j-weight[i]]+value[i]);
}
else
f[i][j]=f[i-1][j];
}
}
cout<<f[N][M]<<endl;//输出最优解
}
上面计算f[i][j]可以看出,在计算f[i][j]时只使用了f[i-1][0……j],没有使用其他子问题,因此在存储子问题的解时,
只存储f[i-1]子问题的解即可。这样可以用两个一维数组解决,一个存储子问题,一个存储正在解决的子问题.
f[j]=max(f[j],f[j-weight[i]]+value[i])
#include<iostream>
using namespacestd;
#define V 1500
unsigned int f[V];//全局变量,自动初始化为0
unsigned int weight[10];
unsigned int value[10];
#define max(x,y) (x)>(y)?(x):(y)
int main()
{
int N,M;
cin>>N;//物品个数
cin>>M;//背包容量
for (int i=1;i<=N; i++)
{
cin>>weight[i]>>value[i];
}
for (int i=1; i<=N; i++){
for (int j=M; j>=weight[i]; j--)
{
f[j]=max(f[j],f[j-weight[i]]+value[i]);
}
}
cout<<f[M]<<endl;//输出最优解
}
而这个问题可以将M设置为total/2,即可。
#include<iostream>
#include <math.h>
using namespacestd;
#define V 2500000
unsigned int f[V];//全局变量,自动初始化为0
unsigned int weight[22];
#define max(x,y) (x)>(y)?(x):(y)
int main()
{
int N,M;
cin>>N;//物品个数
int total =0;
for (int i=1;i<=N; i++)
{
cin>>weight[i];
total = weight[i] + total;
}
M = total/2;
for (int i=1; i<=N; i++){
for (int j=M; j>=weight[i]; j--)
{
f[j]=max(f[j],f[j-weight[i]]+weight[i]);
}
}
int temp = (total-f[M])-f[M];
cout<<abs(temp)<<endl;//输出最优解
}