AcWing 1022 宠物小精灵之收服(01背包问题 二维背包问题) 题解 (动态规划—DP—背包问题)

原题传送门

#include<bits/stdc++.h>

using namespace std;

const int N = 1314, M = 510;

int n, m, k;
int f[N][M];//f[N][M]记录的是损耗的精灵球不超过,皮卡丘消耗的体力不超过M的情况下,捕捉的精灵的个数

int main()
{
	cin>>n>>m>>k;
	for(int i = 0; i < k; i ++ ){
		int v1, v2;
		cin>>v1>>v2;
		for(int j = n; j >= v1; j -- ){//遍历精灵球数,从大往小进行遍历是为了避免数量小的状态影响数量大的状态的计算(详情见01背包的一维优化) 
			for(int k = m - 1; k >= v2; k -- ){//枚举皮卡丘的体力值,因为皮卡丘的体力值不能为0,所以k的初值为m-1,避免出现皮卡丘体力为0的情况 
				f[j][k] = max(f[j][k], f[j - v1][k - v2] + 1);//状态转移方程,因为每次只能多捕一个精灵,所以是+1 
			} 
		}
	}
	cout<<f[n][m - 1]<<" ";
	
	int k = m - 1;//k记录的是捕精灵时消耗的体力
	while(k > 0 && f[n][k - 1] == f[n][m - 1]) k -- ;
	/*
	f[n][m - 1] == f[n][k - 1]记录的是皮卡丘体力消耗为m-1情况下能捕到的最大精灵数
	f[n][1~m-1]应该是个递增序列,当精灵球数固定时,可以消耗的体力数越多,则可以捕到的精灵越多(客观事实吧),所以可以直接用while循环 
	while循环进行第一重时,实际上就是在比较皮卡丘体力消耗为m-2时能不能捕到这么多,如果等号成立,就可以让k--,表示最小体力消耗为m-2...循环以此类推
	之所以是用k-1去比,是因为要先确定少消耗一点体力能不能保证捕到的精灵数不减少,如果可以,就让k--,如果不行,循环结束,输出m-k
	(课上这一段讲的很模糊,自己悟了悟才明白,悟的过程和恍然大明白的时刻,也许就是算法的乐趣所在吧,也许就是我的坚持所在吧) 
	*/ 
	cout<<m - k<<endl;//k是消耗的体力,题中要求输出的是剩余的最大体力 
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值