//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;
}
//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;
}