牛客 codejan与旅行(枚举+贪心)

这道题首先可以想到可以是一直走到某地,或者在某两个地方徘徊。

首先我们要想到当前点第一次肯定要走到左边或者右边的第一个点,这是第一步。

其次,在这个基础上,我们枚举所有的边,当作徘徊的边,这样就遍历了所有情况,另外,当距离长度为m的时候,我们正好顺手做了直达的情况。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
const int mod=1e9+7;
typedef long long ll;
int pos[N];
signed main(){
    int t;
    cin>>t;
    while(t--){
        int n,m,p;
        cin>>n>>m>>p;
        int i;
        int x=0;
        for(i=1;i<=n;i++){
            scanf("%lld",&pos[i]);
            if(pos[i]<p)
                x=i;
        }
        ll ans=1e18;
        for(i=1;i<n;i++){
            if(i<=x){
                if(x-i+1>m)
                    continue;
                int tmp=m-(x-i+1);//徘徊的次数
                int dis=p-pos[i];//到某点的长度
                ans=min(ans,dis+tmp*(pos[i+1]-pos[i]));
                if(tmp&&x+i<=n){//如果可以走到当前点的右边
                    ans=min(ans,dis+2*(pos[x+1]-p)+(tmp-1)*(pos[i+1]-pos[i]));
                }
            }
            else{
                if(i-x>m)
                    continue;
                int tmp=m-(i-x);//当剩下一次的时候,就是走到了终点n
                int dis=pos[i]-p;
                ans=min(ans,dis+tmp*(pos[i+1]-pos[i]));
                if(tmp&&x>=1){
                    ans=min(ans,dis+2*(p-pos[x])+(tmp-1)*(pos[i+1]-pos[i]));
                }
            }
        }
        cout<<ans<<endl;
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12918446.html