周测(十一):纪念品、购买商品

本文探讨了两个涉及动态规划的背包问题。第一个是完全背包问题,通过二维DP数组求解,强调了空间复杂度的控制。第二个问题结合了01背包和完全背包,寻找最大价值的商品购买方案。文章通过实例解析了状态转移方程,并提供了优化空间利用的方法。
摘要由CSDN通过智能技术生成

纪念品

先把重头戏上了:题目链接
然后是解答

==注意空间!!!!==这道题的空间范围我反复改了三次……还是对每个数组对应的数据掌握的不好。
二维空间千万别开到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;
}
//有没有办法可以记录下最大的消耗是多少?
//最大的消耗就是最大价值的最小体积需要多少
//记录下最大的价值,每当出现一个比当前价值大的体积的时候我们就将这个体积记录!!!!! 

接下来时两道模板题……不解释了

疯狂的采药

宝物筛选

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值