zoukankan      html  css  js  c++  java
  • luogu1156垃圾陷阱题解--背包DP

    题目链接

    https://www.luogu.org/problemnew/show/P1156

    方法1

    分析

    将已经爬的高度看作背包容积,最大剩余血量看作价值,(f[i][j])表示吃完第(i)个垃圾,爬到(j)高度的最大剩余血量

    (f[i][j+h[i]]=max(f[i][j+h[i]],f[i-1][j]-(t[i]-t[i-1])))

    (f[i][j]=max(f[i][j],f[i-1][j]+c[i]-(t[i]-t[i-1])))

    当然还要判断能否撑到下一个垃圾的到来,以及判断是否已经爬出了陷阱

    如果不能爬出,显然将垃圾全部吃完是最优的,因为垃圾全用来吃了并且没撑到下一个时刻,所以(ans=max(ans,f[i][0]+t[i]))

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    #include <cstdlib>
    #include <iostream>
    #define ll long long 
    #define ri register int 
    using std::min;
    using std::max;
    template <class T>inline void read(T &x){
    	x=0;int ne=0;char c;
    	while(!isdigit(c=getchar()))ne=c=='-';
    	x=c-48;
    	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    	x=ne?-x:x;return ;
    }
    const int maxn=1005;
    const int inf=0x7fffffff;
    int f[maxn][105];
    bool e[maxn];
    int l,m,n;
    struct Tra{
    	int t,c,h;
    	bool operator <(const Tra &b)const{
    		return t==b.t?c>b.c:t<b.t;
    	}
    }tra[maxn];
    int main(){
    	int dta,h,ans=10;
    	read(l),read(n);
    	for(ri i=1;i<=n;i++){
    		read(tra[i].t),read(tra[i].c),read(tra[i].h);
    	}
    	std::sort(tra+1,tra+1+n);
    	memset(f,-1,sizeof(f));
    	f[0][0]=10;
    	for(ri i=1;i<=n;i++){
    		h=tra[i].h;
    		dta=tra[i].t-tra[i-1].t;
    		for(ri j=l;j>=0;j--){
    			if(f[i-1][j]==-1||f[i-1][j]<dta)continue;
    			if(j+h>=l){
    				printf("%d
    ",tra[i].t);
    				return 0;
    			}
    			f[i][j+h]=max(f[i-1][j]-dta,f[i][j+h]);
    			f[i][j]=max(f[i-1][j]+tra[i].c-dta,f[i][j]);	
    		}
    		if(f[i][0]!=-1)ans=max(ans,f[i][0]+tra[i].t);
        /*注意加特判*/
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    方法2

    分析

    刚刚的方法一点也不背包,我们按着01背包套路把它变成一维的,(f[j])表示爬到了高度(j)总共加上的最大血量.

    (f[j+h[i]]=max(f[j+h[i]],f[j]))

    (f[j]+=c[i])

    按照套路,为了使(j+h[i])这个状态在本阶段中不再出现,我们倒序枚举高度

    代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    #define ll long long 
    #define ri register int 
    using std::min;
    using std::max;
    template <class T>inline void read(T &x){
    	x=0;int ne=0;char c;
    	while(!isdigit(c=getchar()))ne=c=='-';
    	x=c-48;
    	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    	x=ne?-x:x;return ;
    }
    const int maxn=1005;
    const int inf=0x7ffffff;
    int m,n;
    struct Tra{
    	int t,c,h;
    	bool operator <(const Tra &b)const{
    		return t<b.t;
     	}
    }tr[maxn];
    int f[maxn];
    int main(){
    	read(m),read(n);
    	for(ri i=1;i<=n;i++){
    		read(tr[i].t),read(tr[i].c),read(tr[i].h);
    	}
    	std::sort(tr+1,tr+1+n);
    	memset(f,-1,sizeof(f));
    	f[0]=10;
    	for(ri i=1;i<=n;i++){
    		for(ri j=m;j>=0;j--){
    			if(f[j]>=tr[i].t){
    				if(j+tr[i].h>=m){
    					printf("%d
    ",tr[i].t);
    					return 0;
    				}
    				f[j+tr[i].h]=max(f[j+tr[i].h],f[j]);
    				f[j]+=tr[i].c;
    			}
    		}
    	}
    	printf("%d
    ",f[0]);
    	return 0;
    }
    
  • 相关阅读:
    Hibernate----面试题
    Java框架部分---面试题
    面试题---多线程
    swap分区
    Linux之格式化与挂载
    Linux下的GPT分区
    Linux下的MBR分区
    vim基础初步
    管道符,通配符以及其他特殊符号
    shell基础之脚本执行,命令别名以及快捷键等
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9628325.html
Copyright © 2011-2022 走看看