填表法与刷表法

填表法

填表法及f[i]f[i1]等类似的已经更新过的状态转移过来一般比较习惯用填表法(比较好想)

刷表法

刷表法及用f[i]去更新f[i+1]等之后未更新完全的状态(后面的状态可能会被之前的多个状态更新)
虽然用的少但是在一些题上用刷表法会比填表法要更加方便

在状态没有明确的上界时宜用刷表

填表法eg:

状态比较好想将几个需要的状态列出来
i:选到了哪个物品(提前排好序当满足条件时当前物品的时间既是答案)
h:当前到达的高度
hp当前所有能活到的时间
设状态:f[i][j]为选到第i个物品到达j的高度所能到达的最大hp
此题若用填表法边界情况处理起来很麻烦
尤其是在高度的那一维
因为如果高度超过D也可以出井而高度的上限就很难处理
而用刷表法当可以到达某一高度且高度大于D直接输出然后return 0即可
如果到不了D前面则不会return 0就直接把扔下来的垃圾全吃掉直到挺不到下一个垃圾的到来(好凄惨)

P1156 垃圾陷阱

题目描述

卡门――农夫约翰极其珍视的一条 Holsteins 奶牛――已经落了到 “垃圾井” 中。“垃圾井” 是农夫们扔垃圾的地方,它的深度为 D2D100)英尺。

卡门想把垃圾堆起来,等到堆得高度大等于于井的深度时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。

每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。

假设卡门预先知道了每个垃圾扔下的时间 t1t1000),以及每个垃圾堆放的高度 h1h25)和吃进该垃圾能维持生命的时间 f1f30),要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续 10 小时的能量,如果卡门 10 小时内(不含 10 小时,维持生命的时间同)没有进食,卡门就将饿死。

输入格式

第一行为两个整数,DG1G100),G为被投入井的垃圾的数量。

第二到第 G+1 行每行包括三个整数:T1T1000),表示垃圾被投进井中的时间;F1F30),表示该垃圾能维持卡门生命的时间;和 H1H25),该垃圾能垫高的高度。

输出格式

如果卡门可以爬出陷阱,输出一个整数,表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。

样例 #1

样例输入 #1

20 4
5 4 9
9 3 2
12 6 10
13 1 1

样例输出 #1

13

提示

【样例说明】

卡门堆放她收到的第一个垃圾:height=9

卡门吃掉她收到的第 2 个垃圾,使她的生命从 10 小时延伸到 13 小时;

卡门堆放第 3 个垃圾,height=19

卡门堆放第 4 个垃圾,height=20

std:

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n,m;
struct A
{
	int t,g,h;
}a[N];
bool cmp(A x,A y){return x.t < y.t;}
int f[N][110]; 
int sumh;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= m;i++)scanf("%d%d%d",&a[i].t,&a[i].g,&a[i].h);
	sort(a+1,a+1+m,cmp);
	f[0][0] = 10;
	for(int i = 0;i < m;i++)
		for(int j = 0;j <= n;j++)
		{
			if(a[i+1].t <= f[i][j])//hp必须能够挺到$i+1$个垃圾扔下来
			{
				if(j+a[i+1].h >= n)return printf("%d",a[i+1].t),0;
				f[i+1][j+a[i+1].h] = max(f[i+1][j+a[i+1].h],f[i][j]);
				f[i+1][j] = max(f[i+1][j],f[i][j]+a[i+1].g);
			}	
		}
	int sum = 10;//初始值为10
	for(int i = 1;i <= m;i++)
	{
		if(sum < a[i].t)break;
		sum += a[i].g;
	}
	
	printf("%d",sum);
	return 0;
}

另一种状态

f[i][j]为选到第i个物品到达j的生命值所能到达的最大高度
from mhc

#include<bits/stdc++.h>
using namespace std;

const int N=105;
int d,n,f[N][3010];

struct T
{
	int t,life,h;
}t[N];

bool cmp(T a,T b)
{
	return a.t<b.t;
}

int main()
{
	scanf("%d%d",&d,&n);
	int sum=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&t[i].t,&t[i].life,&t[i].h);
		sum+=t[i].life;
	}
	sort(t+1,t+1+n,cmp);
	memset(f,128,sizeof f);
	f[0][10]=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<=sum;j++)
		{
			if(j >= t[i+1].t)
			{
				if(f[i][j]+t[i+1].h >= d)return printf("%d",t[i+1].t),0;
				f[i+1][j+t[i+1].life] =max(f[i+1][j+t[i+1].life],f[i][j]);
				f[i+1][j] = max(f[i+1][j],f[i][j]+t[i+1].h);
			}
		}
	}
	
	sum = 10;
	for(int i = 1;i <= n;i++)
	{
		if(sum < t[i].t)break;
		sum += t[i].life;
	}
	printf("%d",sum);
	return 0;
}

一维优化(第一种状态)

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n,m;
struct A
{
	int t,g,h;
}a[N];
bool cmp(A x,A y){return x.t < y.t;}
int f[110]; 
int sumh;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= m;i++)scanf("%d%d%d",&a[i].t,&a[i].g,&a[i].h);
	sort(a+1,a+1+m,cmp);
	f[0] = 10;
	for(int i = 0;i < m;i++)
		for(int j = n;j >= 0;j--)//倒序
		{
			if(a[i+1].t <= f[j])
			{
				if(j+a[i+1].h >= n)return printf("%d",a[i+1].t),0;
				f[j+a[i+1].h] = max(f[j+a[i+1].h],f[j]);
				f[j] = max(f[j],f[j]+a[i+1].g);
			}	
		}
	int sum = 10;
	for(int i = 1;i <= m;i++)
	{
		if(sum < a[i].t)break;
		sum += a[i].g;
	}
	
	printf("%d",sum);
	return 0;
}
posted @   AC7  阅读(237)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示