P1156 垃圾陷阱

//P1156 垃圾陷阱
//http://www.cnblogs.com/Renyi-Fan/p/7443073.html此文介绍得不错,摘抄如下:
//分析:
//这题是类背包问题的动态规划。
//基本思路是用一个二维数组来存当前高度的生命
//状态决策就是吃和不吃
//这里用bool数组表示存活与否
//a[k].f表示吃了第k件物品恢复的生命值
//假如能吃 f[i][j+a[k].f]=true;
//a[k].h表示用了第k件物品能堆的高度
//假如能用 f[i+a[k].h][j]=true;
//初始状态f[0][10],最开始能存活10分钟
//老外的题目,没说明,就表明输入未必是按时间顺序,故需要排序。
//f[i][j] i表示高度,j表示存活时间,若i高度j时间能存活,则值为1,否则为0
//样例通过,提交,测试点2-3,5-11RE,应该是数组的范围开太小了,重读了一遍题目,发现理解有误 int f[25*100+100][1000+10];//4 此处写成 int f[25+5][1000+10];
//提交,测试点9WA
//查了https://www.luogu.org/discuss/show?postid=6676摘抄如下:
//我的那个点输出的是1000 而答案2900多 ,我是数组开了1000,超过就默认为1000
//重新读题,发现T (0 < T <= 1000) F (1 <= F <= 30) 持续10小时的能量
//最长时间计算10+30*100=3010开得大一些3100,修改,提交AC 2017-9-2 21:15
//该题有两个难点:测试点10,测试点9 即int f[100+50][3100] 开成100+50 3100
//测试点10,开成100+50  深度为D(2<=D<=100)英尺,每个垃圾堆放的高度h(1<=h<=25),跳出井时的最大值估算99+25=124 ,多给些余量 100+50,测试点10 AC
//测试点9,开成3100而不是1000+10 , 重新读题,发现T (0 < T <= 1000) F (1 <= F <= 30) G (1 <= G <= 100) 持续10小时的能量, 最长时间计算10+30*100=3010开得大一些3100 测试点9 AC
#include <stdio.h>
#include <string.h>
struct node{
    int t,f,h;
}a[100+10],tmp;
int f[100+50][3100];//6此处写成 int f[100+50][1000+10]; //重新读题,发现T (0 < T <= 1000) F (1 <= F <= 30) 持续10小时的能量 //最长时间计算10+30*100=3010开得大一些3100 ||   最大值估算99+25=124 修改后测试点10 AC ||5此处写成int f[100+10][1000+10];测试点10RE 4 此处写成 int f[25+5][1000+10];
int main(){
    int d,g,i,j,s=10,k;//2 将s初始化为s=0 s总持续时间
    memset(f,0,sizeof(f));
    scanf("%d%d",&d,&g);
    for(i=1;i<=g;i++){
        scanf("%d%d%d",&a[i].t,&a[i].f,&a[i].h);
        s+=a[i].f;
    }
    f[0][10]=1;
    for(i=1;i<=g;i++)//冒泡排序,按a[].t自小到大排序
        for(j=i+1;j<=g;j++)
            if(a[i].t>a[j].t){
                tmp=a[i];
                a[i]=a[j];
                a[j]=tmp;
            }
    for(k=1;k<=g;k++)
        for(i=d-1;i>=0;i--)//i不从d开始,是为了不把程序写复杂,详见下面程序
            for(j=s;j>=0;j--)
                if(f[i][j]&&a[k].t<=j){//3写成if(f[i][j])//存活
                    f[i+a[k].h][j]=1;//可以垫高
                    if(i+a[k].h>=d){
                        printf("%d\n",a[k].t);
                        return 0;
                    }
                    f[i][j+a[k].f]=1;//1 位置放错,将其错放在if之外//可以吃
                }
    for(i=s;i>=1;i--)
        if(f[0][i]){
            printf("%d\n",i);
            break;
        }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值