我是靠谱客的博主 温柔小霸王,最近开发中收集的这篇文章主要介绍H. The Boomsday Project (dp)题目分析代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目

The 2020 ICPC Asia Shenyang Regional Programming Contest
H. The Boomsday Project

大意:有一个人总是租单车。每次租车要 r 元。现在已知他将来m天的租车情况(每天要租p[i]辆车)。有 n 种优惠卡,第 i 种卡有个期限 d[i] 天(自买卡那天算起到第 d 天结束),可以免去这些天内的 k[i] 次租车钱,买卡要花 c[i] 元,一旦买了一张新卡,那之前的卡全部立即作废。问最少要花多少钱。

n<=500
sum ( p ) <=300000

分析

发现总租车数比较少,就把每次租车独立出来,按顺序进行dp。

先定义一下变量的意义:
cnt 代表着总的租车次数
a[i] 代表第 i 次租车所在的天。
f[i] 代表完成前 i 次租车所需的最少钱数。
ptr[i] 这个后面来解释

先是考虑最朴素的dp:
看伪代码以及里面的注释来理解:
先解释一下里面的 x 的意思:代表着在第 x 次租车结束之后办第 j 种卡,刚好可以免费到第 i 次租车。(若在第 (x-1) 次就不行了),具体的求法好说。

for i: [1 ~ cnt] {	//顺序枚举第 i 次租车
	f[i]= f[i-1]+r;	//先是默认情况,啥优惠都不用
	for j: [1 ~ n]		//枚举使用第 j 种优惠
		for t: [x ~ (i-1)]		//枚举那些使用该种优惠可以影响到第 i 次的那些租车事件
			f[i]= min(f[i], f[t]+c[j])		//看看在第 t 次租车结束后,买一张卡 j ,能否得到更优的效果。(即便有浪费免费次数也不管,反正更便宜了)
}

这样时间复杂度至少是 cnt * sigma(k,d) * (算 x 的时间),好像不太行

然后考虑优化:
注意到第三层循环,实际上是求 f[] 的区间最小值,又注意到 f[] 是递增的,所以那层循环可以直接去掉,最小值肯定是 f[x]。

for i: [1 ~ cnt] {	//顺序枚举第 i 次租车
	f[i]= f[i-1]+r;
	for j: [1 ~ n]		//枚举使用第 j 种优惠
		f[i]=min(f[i], f[x])
}

这样循环就变成两层了,应该行了,接下来就是 x 的求法了。
会发现,随着 i 的增加,对于每个 j 来说, x 也是递增的。那么对每个 j 弄个指针标记记录,一直往右移就行了。这样时间复杂度就单独出来变成了 n * cnt。这也就是前面的 pre[] 数组了。
具体实现看下面的代码。

那这样总的时间复杂度就是 O(cnt * n)。

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;


int n,m;
long long r;
int d[505],k[505];
long long c[505];
int a[300005];
long long f[300005];
int cnt;
int ptr[505];

void solve()
{
	scanf("%d%d%lld",&n,&m,&r);
	for (int i=1; i<=n; i++) scanf("%d%d%lld",&d[i],&k[i],&c[i]);
	for (int i=1,p,q; i<=m; i++) {
		scanf("%d%d",&p,&q);
		for (int i=1; i<=q; i++) a[++cnt]=p;
	}
	
	sort(a+1,a+cnt+1);	//输入不是按天递增的,所以要排序 
	
	for (int i=1; i<=cnt; i++) {
		f[i]=f[i-1]+r;
		for (int j=1,x; j<=n; j++) {
			while (a[i]-a[ptr[j]+1]>=d[j] || i-ptr[j]>k[j]) ptr[j]++;
			f[i]=min(f[i], f[ptr[j]]+c[j]);
		}
	}
	
	printf("%lldn",f[cnt]);
}



int main()
{
	solve();
	return 0;
}

最后

以上就是温柔小霸王为你收集整理的H. The Boomsday Project (dp)题目分析代码的全部内容,希望文章能够帮你解决H. The Boomsday Project (dp)题目分析代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部