首页 > 其他分享 >P3891 [GDOI2014] 采集资源 题解

P3891 [GDOI2014] 采集资源 题解

时间:2024-04-10 17:58:40浏览次数:25  
标签:fr min 题解 P3891 苦工 GDOI2014 ll 资源 tme

题面

看到大家都是两个动态规划的写法,来给大家讲一下只用一次动态规划的写法。

思路

设 \(f_{i,j}\) 表示工作效率为 \(i\),获取 \(j\) 点资源所需的最短时间,不以苦工设状态是因为苦工会因为后面购买而改变,不太现实。\(tme\) 表示答案,即到达 \(t\) 点资源所需的最短时间。

从 \(0\) 到 \(t\) 枚举 \(i\) 和 \(j\),接着枚举每一种苦工,用 \(k\) 表示第 \(k\) 种苦工,需要 \(a_k\) 的资源,效率为 \(b_k\)。像完全背包那样子推。具体的 f[i + b[k]][j - a[k]] = min(f[i + b[k]][j - a[k]] , f[i][j]),表示招募一个苦工,但注意这个苦工所需资源不能超过 \(j\),很容易理解,由于目前状态只要求达到 \(j\) 点资源,当能够购买 \(b_k \ge j\) 的第 \(k\) 种苦工之前,就至少有了 \(j\) 点资源,就没必要再买了。

买了苦工后,自然效率变为 \(i+b_k\),而资金只有 \(j-a_k\),这时的最小时间要么是 \(f_{i+b_k,j-a_k}\),要么就是 \(f_{i,j}\)。这应该是很容易便能想明白的。(因此,\(f\) 数组初始都设为极大值)

如果此时 \(i+b_k \ge t\),说明此时如果买苦工的话效率就已经超过所需的 \(t\) 点资源了,那么 \(tme\) 就需要更新答案,与 \(f_{i,j}+1\) 求一个较小值。为什么是与 \(f_{i,j}+1\) 而不是 \(f_{i+b_k,j-a_k}\) 呢?

首先,\(f_{i+b_k,j-a_k}\) 可能越界。其次,效率超过 \(t\) 时其实就已经没有必要再买了,因为再等待一个单位时间后,现有的资源就变为 \(i+j\) 就会超过 \(t\),感兴趣的同学可以自己去验证一下,所以 \(tme\) 与 \(f_{i,j}\) 取最小值。(这其实也是一个优化,即 \(i+b_k<t\) 才需要更新 \(f\) 数组)

在每次枚举完苦工种类后,也需要考虑如果此后一直不买苦工是否会需要更少的时间就能达到 \(t\) 点资源,即

if(i)
{
	tme = min(tme , (t - j + i - 1) / i + f[i][j]);
}

明显,当 \(i=0\) 时无论如何都不会到达 \(t\),所以从 \(i=1\) 开始判断。同时也要注意当 \(m\) 一开始就大于 \(t\) 时直接输出 \(0\) 即可。

对于每一个 \(f_{i,i+j}\),明显可以由 \(f_{i,j}\) 经过一个时间单位得到,这里也需要对 \(f_{i,i+j}\) 进行更新,即

if(i + j < t)
{
	f[i][i + j] = min(f[i][i + j] , f[i][j] + 1);
}

复杂度 \(O(nt^2)\),能过。

请原谅我拙劣的表达,真的尽力了。

代码

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define fr(i , a , b) for(ll i = a ; i <= b ; ++i)
#define fo(i , a , b) for(ll i = a ; i >= b ; --i)
using namespace std;
inline ll QuickPow(ll a , ll b)
{
	if(b == 0)
	{
		return 1;
	}
	ll k = QuickPow(a , b>>1);
	if(b & 1)
	{
		return (k * k * a) % mod;
	}
	return (k * k) % mod;
}
ll n , m , t;
ll tme = 0x3f3f3f3f;
ll a[10000] , b[10000];
ll f[1001][1001];
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> t;
	memset(f , 0x3f3f3f3f , sizeof(f));
	if(m >= t)
	{
		cout << 0;
		return 0;
	}
	fr(i , 1 , n)
	{
		cin >> a[i] >> b[i];
	}
	fr(i , 1 , m)
	{
		f[0][i] = 0;
	}
	fr(i , 0 , t)
	{
		fr(j , 0 , t)
		{
			fr(k , 1 , n)
			{
				if(a[k] < j)
				{
					f[i + b[k]][j - a[k]] = min(f[i + b[k]][j - a[k]] , f[i][j]);
					if(i + b[k] >= t)
					{
						tme = min(tme , f[i][j] + 1);
					}
				}
			}
			if(i)
			{
				tme = min(tme , (t - j + i - 1) / i + f[i][j]);
			}
			if(i + j < t)
			{
				f[i][i + j] = min(f[i][i + j] , f[i][j] + 1);
			}
		}
	}
	cout << tme;
	return 0;
}

标签:fr,min,题解,P3891,苦工,GDOI2014,ll,资源,tme
From: https://www.cnblogs.com/xhqdmmz/p/18126548

相关文章

  • P8661 [蓝桥杯 2018 省 B] 日志统计 题解
    好久没写题解了,水一篇。这里主要想讲的是不同的处理方法,在阅读本篇题解前请确保读完题。详解一,排序这很好理解,题目要求将热帖从小到大输出,同时题目中还有相对的时间这一概念,因此将输入的\(id\)与\(ts\)按照优先\(id\)其次\(ts\)的排序方式从小到大,排序,这样输出时就没......
  • CF133B Unary 题解
    题面。在考虑如何优化程序时,不要忽略了这题的纯暴力做法。对于样例2此处样例2的输入应该是++++[>,.<-],也许是翻译问题,但并不重要。思路依据题意,将输入的字符串\(s\)转为其对应的二进制串\(str\),在暴力将\(str\)由二进制转为十进制即可。代码为了防止因为幂运算而......
  • CF1913C Game with Multiset 题解
    翻译初始时你有一个空序列,共\(m\)次操作,每次操作读入两个数\(t_i\),\(v_i\),分为以下两种操作:当\(t_i=1\)时,在空序列中加入\(2^{v_i}\)这一元素。(此时\(0\lev_i\le29\))当\(t_i=2\)时,询问是否存在:取当前序列的某些元素,使它们的的和等于\(v_i\)(此时\(0\lev_i\l......
  • CF1913B Swap and Delete 题解
    翻译给定一个字符串\(s\),你有两种操作:删除一个字符。(花费一枚金币)交换某两个字符的位置。(不花费金币)假设经过若干次操作后得到的字符串为\(t\)。\(t\)是好的当且仅当对于任意的\(i\)(\(1\lei\le|t|\),\(|t|\)为字符串\(t\)的长度),均满足\(t_i\nes_i\)。(\(s\)是......
  • CF1907B YetnotherrokenKeoard 题解
    比较简单,建议评橙。题面。思路对于每个给定的字符串,用两个大根堆来分别记录小写字母与大写字母,注意这里记录时不要记录大写的B和小写的b。每当出现一个B时,从记录大写字母的大根堆中取出目前最后录入的大写字母的位置,标记,接着弹出堆顶元素,标记。小写字母同理。以上操作在......
  • CF1891B Deja Vu 题解
    建议凭橙,思路橙,码量红到橙。题面。思路一,暴力直接依照题意模拟,复杂度\(O(tqn^2)\),看一眼数据范围,妥妥T飞,倒在第三个点。二,逐步优化看一眼数据发现,虽然\(q\)很大,但实际上\(x\)只有三十个值,因此首先预处理出从\(2^1\)到\(2^{30}\)的所有值,摘掉一个\(n\),复杂度\(O......
  • P9750 [CSP-J 2023] 一元二次方程 题解
    题面。直接依照题意模拟即可,注意细节。细节第一注意输出分式时分母为\(1\)不输出,分子为\(0\)直接输出零且不带正负号。第二约分时,\(gcd\)内的两个数应该都是非负实数。第三可以单独输出符号,注意别有多余的符号。第四当方程有两根且均是有理数时,要根据\(2a\)的正......
  • CF1815A Ian and Array Sorting 题解
    题面。直接进入主题吧。思路题目要求非递减序列,很明显,由题目给的操作,一定可以将这个序列的前\(n-1\)项能够满足是非递减序列,最后只需要比较第\(n\)项是否大于等于第\(n-1\)项即可。解释一下为什么。对于序列\(a\),从\(a_1\)开始到\(a_{n-1}\)结束,每次对\(a_i\)......
  • CF1909C Heavy Intervals 题解
    一种似乎更快抽象的解法?题面正文看这道题,给定序列\(l,r,c\),要求重构\(l,r,c\)使得\(\sum_{i=1}^n(r_i-l_i)\timesc_i\)最小。首先可以想到的就是尽量让小的\(r_i-l_i\)乘上大的\(c_i\)。这样子看来\(c_i\)几乎不需要更多的处理,仅需从小到大(或从大到小)排个序。来......
  • GitHub问题解决新突破,复旦大学MAGIS框架大幅超越GPT-4
    获取本文论文,请关注公众号【AI论文解读】回复:&nbsp;论文解读引言:GitHub问题解决的挑战与LLMs的潜力在软件开发的演进过程中,解决GitHub仓库中出现的问题是一个复杂的挑战。这不仅涉及到新代码的加入,还要维护现有功能的稳定运行。大型语言模型(LLMs)在代码生成和理解方......