CSP-J 能量消耗

题目描述

在一维数轴上有 n n n 只精灵以及 m m m 个能量球。作为这些精灵的主人,你发现精灵们都因能量用尽而无法移动。精灵可以使用能量球来补充能量。每个能量球都需要花费一定的金币来开启,当一个能量球被开启后,它可以在短时间内给任意数量的精灵提供能量。由于精灵们的能量都用尽了,你只能通过花费金币来将它们传送到指定位置,并且你只能向右传送每个精灵(即传送到坐标更大的位置)。将某个精灵从坐标 x x x 传送到坐标 y y y ( y > x y>x y>x) 需要花费的金币数量为 y − x y-x yx(也就是说,所需的金币为两点的距离)。

现在你需要开启一些能量球,并将每个精灵都传送到某个开启的能量球的坐标上,从而让这 n n n 只精灵都可以进行能量补充。请问你所需花费的金币数最少是多少?注意,多个精灵可以使用同一个能量球。

数据保证每个精灵右边都至少一个能量球。即不存在无解。

输入格式

第一行一个正整数 n n n ,表示精灵的数量。

第二行是 n n n 个用空格隔开的整数 a 1 , … a n a_1,\ldots a_n a1,an,其中 a i a_i ai 表示第 i i i 个精灵所处的坐标。

第三行是一个正整数 m m m,表示能量球的数量。

第四行是 m m m 个用空格隔开的整数 b 1 , … b m b_1,\ldots b_m b1,bm,其中 b i b_i bi 表示第 i i i 个能量球所处的坐标。

第五行是 m m m 个用空格隔开的正整数 c 1 , … c m c_1,\ldots c_m c1,cm,其中 c i c_i ci 表示开启第 i i i 个能量球所需的金币。

数据保证 a 1 ≤ a 2 ≤ … ≤ a n a_1\leq a_2\leq\ldots\leq a_n a1a2an 以及 b 1 ≤ b 2 ≤ … ≤ b m b_1\leq b_2\leq \ldots\leq b_m b1b2bm

输出格式

一行一个正整数,表示所需花费的最少金币数。

代码

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N 1010
#define M 998244353
using namespace std;

ll n,m,num[N],pos[N],qz[N],cnt[N],cst[N],dp[N];

int main()
{
	memset(dp,0x3f,sizeof(dp));
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%lld",&num[i]);
	cin>>m;
	for(int i=1;i<=m;i++) scanf("%lld",&pos[i]);
	for(int i=1;i<=m;i++) scanf("%lld",&cst[i]);
	for(int i=1,j=1;i<=m;i++)
	{
		qz[i]=qz[i-1];
		cnt[i]=cnt[i-1];
		for(;j<=n && num[j]<=pos[i];j++)
		{
			qz[i]+=num[j];
			cnt[i]++;
		}
	}
	
	dp[0] = 0;
	ll ans = INF;
	for(int i=1;i<=m;i++)
	{
		for(int j=0;j<i;j++)
			dp[i]=min(dp[i],dp[j]+(cnt[i]-cnt[j])*pos[i]-(qz[i]-qz[j])+cst[i]);
		if(cnt[i]==n) ans=min(ans,dp[i]);
	}
	cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值