hdu 3016 Man Down

来源:互联网 发布:网络购彩平台 编辑:程序博客网 时间:2024/06/08 03:54

题目大意:

就是一个游戏 叫做 是英雄就下100层。 如果中间人物的血量低于0 就算死亡,输出-1。要求输出人物到达最底层的时候的最大血量。

基本思路:

因为每一块木板只可能从左端或者右端跳下,并且跳下只可能被一块在他以下的木板接住,或者掉到地上。所以我们可以用动态规划的思想求解该问题。其中,dp[i] 表示 当我在第i块木板的时候获得的最大血量(暂时未包括木板带来的伤害或者血量增加效果)。当dp[i]+木板带来的效果<=0的时候,不在该木板上往左或者往右走。

由于木板的数目很多。所以,我们用线段树进行优化预处理出d[i][0]和d[i][1]。两者分别表示第i块木板从左端和从右端往下掉落到哪块木板。

所以,用线段树进行优化相当于:线段树的单点查询,成段更新的操作。具体代码见下:特别的,如果没有第一句的手动扩栈,c++会提示runtime error 栈溢出。

#pragma comment(linker, "/STACK:102400000,102400000");//手动扩栈,防止出现栈溢出的错误#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 400009#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int col[MAXN];//线段树延时标记void downdate(int rt){    if(col[rt]!=-1)    {        col[rt<<1]=col[rt<<1|1]=col[rt];        col[rt]=-1;    }    return ;}void build(int l,int r,int rt){    col[rt]=-1;    if(l==r)    {        return ;    }    int m=(l+r)>>1;    build(lson);    build(rson);}void update(int l,int r,int rt,int ql,int qr,int num)//成段更新{       if(l>=ql&&r<=qr)    {        col[rt]=num;        return ;    } downdate(rt);    int m=(l+r)>>1;    if(m>=ql)update(lson,ql,qr,num);    if(m<qr)update(rson,ql,qr,num);}int query(int l,int r,int rt,int p)//单点查询 {    if(col[rt]!=-1)return col[rt];    if(l==r)return 0;    int m=(l+r)>>1;    if(m<p)return query(rson,p);    else return query(lson,p);}struct node{    int wl,wr,wv,wh;} nod[100009];bool cmp(node a,node b){    return a.wh<b.wh;}int main(){    int n,m,i,j,x,y;    int d[100009][2];    while(scanf("%d",&n)!=-1)    {        build(1,100000,1);        for(i=0; i<n; i++)            scanf("%d%d%d%d",&nod[i].wh,&nod[i].wl,&nod[i].wr,&nod[i].wv);        sort(nod,nod+n,cmp);//在计算d的时候,需要把木板从下往上进行计算更新线段树        for(i=0; i<n; i++)        {            d[i+1][0]=query(1,100000,1,nod[i].wl);            d[i+1][1]=query(1,100000,1,nod[i].wr);            update(1,100000,1,nod[i].wl,nod[i].wr,i+1);        }        int dp[100009];        int ans[100009];        for(i=0;i<n;i++)            dp[i]=-111111;        dp[n]=100;        for(i=n; i>=1; i--)        {            ans[i]=dp[i]+nod[i-1].wv;            if(ans[i]<=0)continue;            int xl=d[i][0];//从第i块木板的左端掉落到达的木板编号            int xr=d[i][1];//从第i块木板的右端掉落到达的木板编号            dp[xl]=max(dp[xl],ans[i]);            dp[xr]=max(dp[xr],ans[i]);        }        ans[0]=dp[0];        if(ans[0]<=0)printf("-1\n");        else printf("%d\n",dp[0]);    }    return 0;}


 

0 0
原创粉丝点击