垃圾陷阱--01背包

Luogu 1156

在这里插入图片描述

题目分析:

  • 定义 f [ i ] [ j ] 表 示 用 前 i 个 垃 圾 , 使 高 度 为 j 的 最 大 生 命 值 f[i][j]表示用前i个垃圾,使高度为j的最大生命值 f[i][j]i使j

  • 边界: f [ i ] [ j ] = − I N F , f [ 0 ] [ 0 ] = 10 f[i][j]=-INF,f[0][0]=10 f[i][j]=INF,f[0][0]=10

  • 转移方程:
    f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i − 1 ] [ j ] − c + w ) f[i][j]=max(f[i][j],f[i-1][j]-c+w) f[i][j]=max(f[i][j],f[i1][j]c+w)
    f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i − 1 ] [ j − h ] − c ) f[i][j]=max(f[i][j],f[i-1][j-h]-c) f[i][j]=max(f[i][j],f[i1][jh]c)

  • i f : f [ i ] [ m ] > = 0 , p r i n t f : t [ i ] if:f[i][m]>=0,printf:t[i] if:f[i][m]>=0,printf:t[i]
    e l s e : a n s = m a x ( a n s , f [ i ] [ 0 ] + t [ i ] ) else :ans=max(ans,f[i][0]+t[i]) else:ans=max(ans,f[i][0]+t[i])

  • 注意使用滚动数组要及时赋初值覆盖以前的值

Code:

#include <bits/stdc++.h>
using namespace std;
#define maxn 110
#define maxm 110
#define INF 213962143

int n,m,f[3][maxm];
struct node {
	int t,w,h;
}e[maxn];

inline int read_() {
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x*f;
}

inline bool cmp_(node aa,node bb) {
	return aa.t < bb.t ;
}

void readda_() {
	m=read_();n=read_();
	for(int i=1;i<=n;++i) {
		e[i].t=read_();e[i].w=read_();e[i].h=read_();
	}
	sort(e+1,e+n+1,cmp_);
	memset(f,-0x7f,sizeof(f));
	f[0][0]=10;
	e[0].t=0;
	int ans=0;
	for(int i=1;i<=n;++i) {
		for(int j=0;j<=m;++j) {
			f[(i&1)][j]=-INF;
			if(f[(i&1)^1][j]>=(e[i].t-e[i-1].t)) {
				f[i&1][j]=max(f[i&1][j],f[(i&1)^1][j]-(e[i].t-e[i-1].t)+e[i].w);
			}			
			if((j-e[i].h)>=0&&f[(i&1)^1][j-e[i].h]>=(e[i].t-e[i-1].t)) {
				f[i&1][j]=max(f[i&1][j],f[(i&1)^1][j-e[i].h]-(e[i].t-e[i-1].t));
			}			

		}
		if(f[i&1][m]>=0) {
			printf("%d",e[i].t);
			return;
		}
		ans=max(ans,f[i&1][0]+e[i].t);
	} 
	printf("%d",ans);
}

int main() {
	freopen("a.txt","r",stdin);
	readda_();
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值