动态规划,背包问题变型

题目:UVALive - 4870

题意:坐过山车,可以兴奋,可以头晕。对于每一段路,你可以闭眼睛,也可以睁开眼睛。

如果睁开眼睛,会得到一定的兴奋值,也会产生一定的眩晕值。如果闭上眼睛,会减少一定的眩晕值,

但不会得到兴奋值。求不超过一个给定眩晕值情况下,得到的最大兴奋值。

另外,眩晕值初始为0,也不会低于0。


Input

There will be several test cases in the input. Each test case will begin with a line with three integers:


N K L


Where N(1,1 000)(闭合) is the number of sections in this particular roller coaster, K(1,500) (闭合)is the amount that Bessie's dizziness level will go down if she keeps her eyes closed on any section of the ride, and L(1,300 000)(闭合) is the limit of dizziness that Bessie can tolerate - if her dizziness ever becomes larger than L, Bessie will get sick, and that's not fun!

Each of the next N lines will describe a section of the roller coaster, and will have two integers:


F D


Where F(120) is the increase to Bessie's total fun that she'll get if she keeps her eyes open on that section, and D(1500) is the increase to her dizziness level if she keeps her eyes open on that section. The sections will be listed in order. The input will end with a line with three 0s.

Output

For each test case, output a single integer, representing the maximum amount of fun Bessie can have on that roller coaster without exceeding her dizziness limit. Print each integer on its own line with no spaces. Do not print any blank lines between answers.

Sample Input

3 1 2 
2 1 
3 1 
5 2 
10 5 1 
20 2 
12 4 
3 3 
10 6 
20 3 
19 9 
19 7 
1 500 
15 5 
4 2 
0 0 0

Sample Output

7 
0


定义:dp[i+1][j]表示前i段路中挑选出兴奋值总和为j时,总眩晕值的最小量(不存在时就是一个充分大的数值inf)。

dp[0][0] = 0

dp[0][j] = inf


#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
const int maxv = 20;
const int inf = 999999;
int v[maxn];//得到的价值
int w[maxn];//重量
int N,K,L;
int dp[maxn][maxn*maxv];
void solve() {
	fill(dp[0],dp[0]+maxn*maxv,inf);
	
	
	dp[0][0] = 0;
	for(int i=0; i<N; i++) {
		for(int j=0; j<=maxn*maxv; j++) {
			
			if(j<v[i]) {
				if(dp[i][j]==inf) dp[i+1][j] = dp[i][j];//上一个值不存在,下一个值直接不存在 
				else dp[i+1][j] = dp[i][j]-K;//第i段不睁眼,眩晕减掉k 
			
				if(dp[i+1][j]<0) dp[i+1][j] = 0;//眩晕不能低于0 
			} else {
				int x;
				if(dp[i][j]==inf) {
					x = dp[i][j];
				} else {
					x = dp[i][j]-K;
					if(x<0) x = 0;
				}
				int y;
				if(dp[i][j-v[i]]==inf) {
					y = dp[i][j-v[i]];
				} else {
					y = dp[i][j-v[i]]+w[i];
				}
				
				
				if(y<=L||x<=L)//至少有一个不能超过最大眩晕值 
				dp[i+1][j] = min(x,y);
				else dp[i+1][j] = inf;
			}
		}
	}
	int res = 0;
//	for(int i=0;i<=N;i++){
//		for(int j=0;j<=2;j++){
//			cout<<dp[i][j]<<' ';
//		}
//		cout<<endl;
//	}
	for(int i=0; i<=N*maxv; i++) {
		//选出满足条件的最大的j 
		if(dp[N][i]<=L) {
			res = i;			
		}
	}
	cout<<res<<endl;
}
int main() {
	while(cin>>N>>K>>L) {
		if(!N&&!K&&!L) return 0;
		for(int i=0; i<N; i++) {
			cin>>v[i]>>w[i];
		}
		solve();
	}
}


可以优化为一维dp。。。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值