题解
题目说了,最终的答案只和走的路径长度有关,交付的代价是固定的。
拿最后一个样例说明,最大携带量为10,三个点需求分别为5 0 8,如果最先满足第一个点5则还有剩余物品,有两个选择要么是继续向后走,要么是回起点重新补充。
继续向后走剩余的5个对于8个来说还不能满足,则需要再走一趟到最后一个点,这样代价就会高。
如果选择会起点补充则相当于浪费了5个物品,对于这个样例来说不会亏但是肯定也不会赚。
则贪心思路为尽量先供应最后面的点,接受的时候使用一个p记录最后的点再那个位置,每次行走代价就是p*30(来回一趟),如果当前点供应完毕则令p–向前移动。
具体看代码,备注比较详细。
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 100;
int a[N];
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int T;
cin >> T;
while (T--)
{
int m, n, p = 0; //p最后一个有效点
scanf("%d%d", &m, &n);
ll ans = 0;
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
if (a[i])
p = i;
}
while (p)
{
ans += p * 30; //到p再回原点代价
int t = m; //身上所带物品
while (p && t)
{
int e = min(t, a[p]); //交付
t -= e;
a[p] -= e;
ans += e * 3; //交付代价
while (p && !a[p]) //如果当前点已经送完则移动p
p--;
}
}
printf("%lld\n", ans);
}
return 0;
}