这道题首先可以想到可以是一直走到某地,或者在某两个地方徘徊。
首先我们要想到当前点第一次肯定要走到左边或者右边的第一个点,这是第一步。
其次,在这个基础上,我们枚举所有的边,当作徘徊的边,这样就遍历了所有情况,另外,当距离长度为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; } }