题解:运送物资 [GESP六级]
2025-12-21 22:23:57
发布于:山东
8阅读
0回复
0点赞
首先考虑列出每辆车的总行驶路程:s=2*a[i]*p+2*b[i]*(x-p)
根据直觉,a[i]>b[i]的车应当优先分配靠左的p[x],a[i]<b[i]的车应该优先分配靠右的p[x],所以需要排序解决
那怎么排序呢?
在所有a[i]>b[i]的车中,贪心地想,a[i]越多的应该越靠左,但同时也要考虑b[i]的影响,所以应该是a[i]-b[i]越大的越靠左安排;(a[i]<b[i]同理)
证明:排序不等式 适用于代价两两不相关的交换/排序问题
假设对于两辆车i,j,i在p1,j在p2,如果把i移到j更优,就要求原来的总代价大于交换后的总代价,即:
2*a[i]*p1+2*b[i]*(x-p1) + 2*a[j]*p2+2*b[j]*(x-p2) > 2*a[i]*p2+2*b[i]*(x-p2) + 2*a[j]*p1+2*b[j]*(x-p1)
=> a[i]*p1 - b[i]*p1 + a[j]*p2 - b[j]*p2 > a[i]*p2 - b[i]*p2 + a[j]*p1 - b[j]*p1
=> a[i]*(p1-p2) + b[i]*(p2-p1) > a[j]*(p1-p2) + b[j]*(p2-p1)
=> (a[i]-b[i])(p1-p2) > (a[j]-b[j])(p1-p2)
=> a[i]-b[i] > a[j]-b[j]
然后贪心模拟即可,注意a[i]=b[i]的情况可以与a[i]>b[i]的情况一同处理变成a[i]>=b[i]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int n, m, x, cnt1, cnt2;
struct Info{ int p, c; }t[N]; // 运输站点
struct Node{ int a, b; }f[N], g[N]; // 货车 f:a[i]>=b[i] g:a[i]<b[i]
void solve()
{
cin >> n >> m >> x;
for(int i = 1; i <= n; i ++){
cin >> t[i].p >> t[i].c;
}
for(int i = 1; i <= m; i ++){
int aa, bb; cin >> aa >> bb;
if(aa >= bb) f[++cnt1] = {aa, bb};
else g[++cnt2] = {aa, bb};
}
sort(t + 1, t + n + 1, [](Info p1, Info p2){ return p1.p < p2.p; });
sort(f + 1, f + cnt1 + 1, [](Node p1, Node p2){ return p1.a-p1.b > p2.a-p2.b; });
sort(g + 1, g + cnt2 + 1, [](Node p1, Node p2){ return p1.b-p1.a > p2.b-p2.a; });
int now = 1; ll ans = 0;
for(int i = 1; i <= cnt1; i ++){
if(t[now].c == 0) now ++;
ans += 2LL*f[i].a*t[now].p + 2LL*f[i].b*(x-t[now].p);
t[now].c --;
}
now = n;
for(int i = 1; i <= cnt2; i ++){
if(t[now].c == 0) now --;
ans += 2LL*g[i].a*t[now].p + 2LL*g[i].b*(x-t[now].p);
t[now].c --;
}
cout << ans << '\n';
}
signed main()
{
ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
solve();
return 0;
}
这里空空如也




有帮助,赞一个