Codeforces Round #366 (Div. 1) B

题意

规定起点、终点。
遍历所有点,从一点向左向右跳到某个点的贡献不同。并且一个点只能访问有且只有一次。

题解

做法一: d p dp
我们可以规定每个点的入边、出边,可以发现转移式子。
但是苦于不理解起点终点的特殊情况。暂不提供题解。

做法二:贪心
起点到终点 s t o e s\quad to\quad e
往里面一个一个插入点,每次插入的时候把旧的贡献去掉加上新的贡献。
然后找到最佳位置。

这是可撤销的贪心,所以正确。
写个链表即可。

#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;
}

发布了203 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/mxYlulu/article/details/104158988