题意
规定起点、终点。
遍历所有点,从一点向左向右跳到某个点的贡献不同。并且一个点只能访问有且只有一次。
题解
做法一:
我们可以规定每个点的入边、出边,可以发现转移式子。
但是苦于不理解起点终点的特殊情况。暂不提供题解。
做法二:贪心
起点到终点
往里面一个一个插入点,每次插入的时候把旧的贡献去掉加上新的贡献。
然后找到最佳位置。
这是可撤销的贪心,所以正确。
写个链表即可。
#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
using namespace std;
typedef long long ll;
const int maxn = 350050;
int x[maxn],a[maxn],b[maxn],c[maxn],d[maxn];
int nxt[5050];
ll dist(int i,int j){
if(i>j)return abs(x[i]-x[j])+1ll*c[i]+1ll*b[j];
else return abs(x[i]-x[j])+1ll*d[i]+1ll*a[j];
}
void insert(int x,int y){
nxt[y]=nxt[x];
nxt[x]=y;
}
int main(){
int n,s,e;cin>>n>>s>>e;
FOR(i,1,n)sf(x[i]);
FOR(i,1,n)sf(a[i]);
FOR(i,1,n)sf(b[i]);
FOR(i,1,n)sf(c[i]);
FOR(i,1,n)sf(d[i]);
int l=s,r=e;
nxt[s]=e;
nxt[e]=-1;
ll ans=dist(s,e);
for(int i=1;i<=n;i++)if(i!=s&&i!=e){
ll Mix=0x3f3f3f3f3f3f3f3f,id;
for(int j=s;nxt[j]!=-1;j=nxt[j]){
ll tmp=dist(j,i)+dist(i,nxt[j])-dist(j,nxt[j]);
if(tmp<Mix){
Mix=tmp;
id=j;
}
}
ans+=Mix;
insert(id,i);
}
cout<<ans<<endl;
}
来源:CSDN
作者:mxYlulu
链接:https://blog.csdn.net/mxYlulu/article/details/104158988