AcWing 1022. 宠物小精灵之收服_0/1背包

题目链接:https://www.acwing.com/problem/content/1024/

解题思路:
这道题就是一道0/1背包问题,但是我们在DP的时候需要同时DP2个状态,一个是为了得到最多精灵数,另一个得到最少的体力,同时需要注意这道题目中体力不能为0,而精灵球的数目可以为0(细节),另外这道题目需要用到滚动数组,要不然内存会超。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 1005;

int cnt[maxn], pain[maxn];
int f[1005][505];
int c_pain[1005][505];

int N, M, K;

int main(void) {
	scanf("%d%d%d", &N, &M, &K);
	for(int i = 1; i <= K; i ++)
		scanf("%d%d", &cnt[i], &pain[i]);
		
	for(int i = 1; i <= K; i ++)   //精灵的数量 
		for(int j = N; j >= cnt[i]; j --)     //需要消耗的精灵球的数量 
			for(int k = M; k > pain[i]; k --) {     //需要消耗的体力 
				if(f[j][k] < f[j - cnt[i]][k - pain[i]] + 1) {
					f[j][k] = f[j - cnt[i]][k - pain[i]] + 1;
					c_pain[j][k] = c_pain[j - cnt[i]][k - pain[i]] + pain[i];
				} else if(f[j][k] == f[j - cnt[i]][k - pain[i]] + 1) {
					c_pain[j][k] = min(c_pain[j][k], c_pain[j - cnt[i]][k - pain[i]] + pain[i]);
				}
				
			}
	
	printf("%d %d\n", f[N][M], M - c_pain[N][M]);
	
	return 0;
} 

总结:在做DP问题的时候我们在一开始最好是先算一下我们最大可以开多大的内存,另外审题要仔细。

发布了136 篇原创文章 · 获赞 0 · 访问量 2993

猜你喜欢

转载自blog.csdn.net/weixin_42596275/article/details/101836931