题目描述
在一维数轴上有 n n n 只精灵以及 m m m 个能量球。作为这些精灵的主人,你发现精灵们都因能量用尽而无法移动。精灵可以使用能量球来补充能量。每个能量球都需要花费一定的金币来开启,当一个能量球被开启后,它可以在短时间内给任意数量的精灵提供能量。由于精灵们的能量都用尽了,你只能通过花费金币来将它们传送到指定位置,并且你只能向右传送每个精灵(即传送到坐标更大的位置)。将某个精灵从坐标 x x x 传送到坐标 y y y ( y > x y>x y>x) 需要花费的金币数量为 y − x y-x y−x(也就是说,所需的金币为两点的距离)。
现在你需要开启一些能量球,并将每个精灵都传送到某个开启的能量球的坐标上,从而让这 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 a1≤a2≤…≤an 以及 b 1 ≤ b 2 ≤ … ≤ b m b_1\leq b_2\leq \ldots\leq b_m b1≤b2≤…≤bm。
输出格式
一行一个正整数,表示所需花费的最少金币数。
代码
#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;
}