01背包问题思想是将将总数进行拆分,拆分成每块钱(每个重量基数)。
算法实现是将每个物体抽象为一行,每一列为总数的细分,再分别从物体本身的价格(重量)到总数循环,每一次都进行f[i]=max{f[i],f[i-v[j]]+v[i]*w[i]}(f[i]为每一格的最大收益,v[i]为物体价格/重量,w[i]为物体价值) 的比较,这样执行完每一行都可以刷新这个价格(重量)区间的最大收益
#include<iostream>
#include<algorithm>
using namespace std;
int N, m;
int sum[30010];
struct thing
{
int price;
int grade;
}things[30];
void input();//输入函数
int main()
{
int i, j;
input();
for (i = 1; i <= m; i++)
for (j =N ; j >=things[i].price; j--)//*从后往前,这样就不是被本行的计算覆盖
sum[j] = max(sum[j], things[i].price*things[i].grade + sum[j - things[i].price]);//计算公式,将问题拆分成每块钱
cout << sum[N];
return 0;
}
void input()
{
cin >> N >> m;
int i;
for (i = 1; i <= m; i++)
cin >> things[i].price >> things[i].grade;
}
#include<iostream>
using namespace std;
const int N = 120;
int v[N], f[N];
int main()
{
int n, m;
int i, j;
f[0] = 1;//当钱正好购买一个菜的时候情况
cin >> n >> m;
for (i = 1; i <= n; i++)
cin >> v[i];
for (i = 1; i <= n; i++)
for (j = m; j >= v[i]; j--)
f[j] = f[j] + f[j - v[i]];//f[j]为不买当前菜的情况数,f[j-v[i]]为买了当前菜用剩下的钱买其他菜的情况数
cout << f[m];
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10010;
struct Med
{
int time, value;
}med[N];
int sum[100010];
int main()
{
int T, M;
int i, j;
cin >> T >> M;
for (i = 1; i <= M; i++)
cin >> med[i].time >> med[i].value;
for (i = 1; i <= M; i++)
for (j = med[i].time; j <= T; j++)//只有这里跟01背包反过来,这样可以不断更新每一个状态的最大价值,可以做到一直取
sum[j] = max( sum[j],med[i].value + sum[j - med[i].time] );
cout << sum[T];
return 0;
}
原文:https://www.cnblogs.com/JMWan233/p/11140817.html