2020沈阳-The Boomsday Project-(线性dp+双指针转移理解)

H

题意:
就是小A会借自行车,给你m个a和b,在第a天借b次。sum(b)<=1e5。然后借一次的价格是k,不过还有n<=500种会员卡,每个会员卡有d天时效,一共k次免费借车,花费c元。现在问你在满足小A借车的情况下花费最少是多少。

思考:

  1. 当时看完感觉不太好做,因为又陷入了那种思想,就是看到第a天借b次,并且一张会员卡有d天时效,k次免费。我怎么去用这些会员卡呢,可能这个卡用了可以对后面的有用,所以就傻逼的感觉不能写了。
  2. 虽然当时我看到sum(b)<=1e5,并且n一共就500个会员卡,可以两种循环,但是dp怎么dp呢?我感觉这不能dp,而且赛时过的也很少,感觉可能是牛逼算法?然后就没看了。
  3. 其实这题和之前做的蓝桥杯的一样:2022蓝桥杯国赛B组-费用报销。把天数都展开,放到数组里,这样就可以对天数进行dp了,反正每天用一次。然后转移的时候,枚举每个物品,看看dp[i]要从哪里转移,如果每次都暴力转移点j,这样复杂度太高了。由于dp的递增性,所以尽量选择越左边的越好,所以有单调性那么完全可以二分或者用个指针idx,如果二分复杂度会高,直接双指针就可以了。
  4. 不过有一点一直卡我的就是,我就想枚举物品,然后枚举m天去dp,反正我每个物品都去更新你一遍就可以了。但是WA24,我就想怎么会错呢。实际上,比如枚举第i个物品的时候,第j个物品还没用过,现在不能保证我枚举的双指针的dp是最小的那个,因为第j个物品还没用,所以此时i之前每个点的dp,都不是真正的dp值,因为后面还会变。所以必须先枚举天数,再枚举物品,让第i天的dp值确定下来,为后面的人去用的时候这个dp就固定了,就可以双指针单调走了。

代码:

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define db double
#define int long long
#define PII pair<int,int >
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

using namespace std;
const int mod = 1e9+7,inf = 1e18;
const int N = 1e6+10,M = 510;

int T,n,m,k;
int va[M],vb[M],vc[M];
int vd[N],cnt;
int idx[N],dp[N];

signed main()
{
	IOS;
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++) cin>>va[i]>>vb[i]>>vc[i];
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		while(b--) vd[++cnt] = a;
	}
	sort(vd+1,vd+1+cnt);
	for(int i=1;i<=cnt;i++) dp[i] = inf;
	for(int i=1;i<=cnt;i++)
	{
		dp[i] = min(dp[i],dp[i-1]+k);
		for(int j=1;j<=n;j++)
		{
			while(idx[j]+1<i&&vd[idx[j]+1]<=vd[i]-va[j]) idx[j]++;
			while(idx[j]+1<i&&i-(idx[j]+1)>=vb[j]) idx[j]++;
			dp[i] = min(dp[i],dp[idx[j]]+vc[j]);
		}
	}
	cout<<dp[cnt];
	return 0;
}

总结:
多多思考一下,不要退却的太早,稍微转化转化,思考一下就是经典的问题。当你看到一些可以用的提示的时候,多多想想怎么用,比如可以循环n*m,如果这样循环的话,你该怎么确定m呢,对吧。这样推一推就推出来了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值