写了个dfs,发现无法记忆化。
然后就不知道了。
后来想到其实最后肯定会找两个点来回走。显然来回走希望这段路是最短的,但是如果要走到这个点的话,距离又不能保证很短,所以就不会了。。

题目大意:
给n个点在一维数轴上有不同的位置,现在给定一个初始点(不在n个点上),问访问m个点(可以重复访问)最少的路程。

思路:
首先dfs肯定是可写的,但是复杂度太高了。
应该可以想到比较理想的情况是在两个点之间走来走去。
假设挑了两个点t和t+1,从p走到t的话这段距离并不一定是值得的(即可能走过来花的路程更长)。
因此直接算是不可行的,不过我们采用枚举t和t+1(这里没想到。。)
那么在到达t之前,我们一定是直接走的!
乍一想好像没错,但是有个hack点,例如3个点(1,10,14),需要访问3个点
初始位置p=2,那么我们从p走到10,然后10和14来回走,一共花费8+4+4=16
实际上,我们可以从p走到1,然后1走到10,再走到14,一共花费1+9+4=14
也就是说,我们可能会先往反方向走一个点,然后再朝着目标点t走。

那有没有可能是反方向走若干个点,再朝目标点t走呢?
这里不会的。
我们回顾刚刚反方向走的目的:其实是让反方向走的路t1,取代最后目标点走来走去的一次路程t2,也就是让t1<t2的时候我们可以先反方向走一下。
此时如果我再往反方向走一格的话,这段路假设为t3,我们其实是希望t3<t2。这样的话,我们直接走t3来回就好了,没有必要跑到t去了。

因此,我们的策略就是枚举走来走去的两个点的位置,然后考虑直接走过去或者反方向走一次然后走过去的情况就好了
这里我把我的dfs改了,也就是在dfs过程中,不需要考虑所有的情况,只要走到某个点时,计算一下当前这个点作为走来走去的点的总路程,最后取最小值就好了。

哎,感觉好难啊。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,pos[100040],p,vis[100004];
long long sum=1e12;
void dfs(int k,int t,long long now){
    if(k==m+1){
        sum=min(sum,now);
        return ;
    }
    if(t>1)sum=min(sum,now+1ll*(m-k+1)*(pos[t]-pos[t-1]));
    if(t<n)sum=min(sum,now+1ll*(m-k+1)*(pos[t+1]-pos[t]));
    if(t>1&&!vis[t-1]){
        vis[t-1]=1;
        dfs(k+1,t-1,now+pos[t]-pos[t-1]);
    }
    if(t<n&&!vis[t+1]){
        vis[t+1]=1;
        dfs(k+1,t+1,now+pos[t+1]-pos[t]);
    }
    return ;
}
int main()
{
    int T;
    cin>>T;
    while(T--){
        sum=1e12;
        cin>>n>>m>>p;
        int x=0;
        for(int i=1;i<=n;i++)cin>>pos[i];
        pos[n+1]=1e9+7;
        for(int i=0;i<=n;i++){
            if(p>pos[i]&&p<pos[i+1]){
                x=i;
                break;
            }
        }
        memset(vis,0,sizeof(vis));
        if(x==0){   //开始只能往右
            vis[1]=1;
            dfs(2,1,pos[1]-p);
        }
        else if(x==n){    //开始只能往左
            vis[n]=1;
            dfs(2,n,p-pos[n]);
        }
        else {    //在中间,尝试往左和往右
            vis[x]=1;
            dfs(2,x,p-pos[x]);
            memset(vis,0,sizeof(vis));
            vis[x+1]=1;
            dfs(2,x+1,pos[x+1]-p);
        }
        cout<<sum<<endl;
    }
    return 0;
}