纪念品
先把重头戏上了:题目链接
然后是解答
==注意空间!!!!==这道题的空间范围我反复改了三次……还是对每个数组对应的数据掌握的不好。
二维空间千万别开到1e4级别的!再往上要三思!
//这是完全背包!
#include<bits/stdc++.h>
using namespace std;
const int T = 110, N = 110, M = 1e4 + 10;
int a[T][N];
//件数,体积
int dp[N][M];
int maxx = -1;
int main(){
//t 天,n件, 当前的金币数
int t, n, m; cin >> t >> n >> m;
for(int i = 1; i <= t; i ++)
for(int j = 1; j <= n; j ++)
//第i天第j件物品的价格
scanf("%d", &a[i][j]);
//然后是枚举t - 1天,最后一天只会卖出
for(int day = 1; day < t; day ++){
//dp用来记录当天的最大收获!
//每一天都要更新一下
memset(dp, 0, sizeof(dp));
//i枚举当天这件物品的情况
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++){
//买不了 ,那就不买
if(j < a[day][i]){
dp[i][j] = dp[i - 1][j];
continue;
}
//买的了至少一件就和不买这一件的同体积的情况对比,
//如果 买这一件 ,那就将价值看做是明天的卖出价值减去今天的买入价值
//这样做有一点贪心的思想在里面,假如有四组数据:10 20 30 ; 10 5 1; 10 20 15; 10 5 30;
//分别代表了四种价值的趋势,你会发现每一种价值趋势 都可以用这个状态转移方程式得到最优解!
dp[i][j] = max(dp[i - 1][j], dp[i][ j - a[day][i] ] + a[day + 1][i] - a[day][i]);
}
}
//将当天的最大收获加起来!
m += dp[n][m];
}
cout << m << endl;
return 0;
}
//数据范围:t = 100 ;n = 100,假设每件物品都是10000……
//很好,不会超出范围
//糟糕……空间忘记算了……爆了……
接下来是一道比较简单的01背包加上完全背包的题目。
购买商品
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
ll MAXX = -1; int maxv;
ll f[N];
int main(){
int m; cin >> m;
//首先是01背包找到可以买到的猫粮 的最大价值 的最小体积是多少
//价格做体积 ,质量做价值
int n; cin >> n;
for(int i = 1; i <= n; i ++){
int v; ll w; scanf("%d%lld", &v, &w);
for(int j = m; j >= v; j --){
f[j] = max(f[j], f[j - v] + w);
//接下来就是找到最大的体积
if(f[j] > MAXX){ MAXX = f[j], maxv = j;}
if(f[j] == MAXX && maxv > j) maxv = j;
}
}
//然后就是把这个 最大价值的消费给减去.
m -= maxv;
memset(f, 0, sizeof f);
// 然后是一个简单的完全背包。
int x; cin >> x;
for(int i = 1; i <= x; i ++){
int v; ll w; scanf("%d%lld", &v, &w);
for(int j = v; j <= m; j ++)
f[j] = max(f[j], f[j - v] + w);
}
cout << f[m];
return 0;
}
//有没有办法可以记录下最大的消耗是多少?
//最大的消耗就是最大价值的最小体积需要多少
//记录下最大的价值,每当出现一个比当前价值大的体积的时候我们就将这个体积记录!!!!!
接下来时两道模板题……不解释了