cf1504. Travelling Salesman Problem
题意:
n个城市,编号1~n,每个城市有美丽值a[i],现在要从城市1出发,其他所有城市走一遍,最后回到城市1,城市i到j的花费为max(ci,aj-ai),ci为第i个城市的最低消费
最低的总消费是多少?
题解:
(题解来自官方题解)
费用 = max (ci ,aj - ai)= ci +max(0,aj-ai-ci)
因为所有城市都要经过,所以ci是固定消费,我们现在要做的就是最小化max(0,aj-ai-ci)的总和
我们注意ai,ci一定是大于0的,要让这个max最小化,我们就尽可能让他等于0,也就是aj - (ai+ci)<=0
如果ai>aj,那么从城市i到城市j就是免费的(这里不考虑固定的ci消费,只考虑max的情况),所以我们只需要找一条从a1到an的路,剩下的旅程可以免费完成,因为最短路径是最优的
贴上原题解(说实话我现在还不是很清楚,等脑子清楚了再解决)
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
vector<pair<long long, long long>> ve;
long long ans = 0;
for(int i = 0; i < n; i++) {
long long a, c;
cin >> a >> c;
ve.push_back({
a, c});
ans += c;
}
sort(ve.begin(), ve.end());//以a为第一元素,b为第二元素
//城市的美丽值是递增的
//for(int i=0;i<n;i++)
// cout<<ve[i].first<<" "<<ve[i].second<<endl;
long long mx = ve[0].first + ve[0].second;
for(int i = 1; i < n; i++) {
ans += max(0LL, ve[i].first - mx);
mx = max(mx, ve[i].first + ve[i].second);
}
cout << ans << '\n';
}
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<pair<long long, long long> > city;
long long ans = 0;
for(int i = 0; i < n; i++) {
long long a, c;
cin >> a >> c;
city.push_back({
a, c});
ans += c;
}
sort(city.begin(), city.end());
priority_queue<pair<long long, int>> Q;
vector<bool> vis(n, false);
Q.push({
0, 0});
while(!Q.empty())
{
long long d; int i;
tie(d, i) = Q.top();//返回指向绑定的输出流的指针。
Q.pop();
if(vis[i]) continue;
vis[i] = true;
if(i == n - 1) {
ans -= d;
break;
}
if(i > 0) {
Q.push({
d, i - 1});
}
int j = lower_bound(city.begin(), city.end(), make_pair(city[i].first + city[i].second, LLONG_MAX)) - city.begin() - 1;
//LLONG_MAX均存在与头文件limits.h,表示long long int
Q.push({
d, j});
if(j + 1 < n) {
Q.push({
d - city[j + 1].first + city[i].first + city[i].second, j + 1});
}
}
cout << ans << '\n';
}