这个题我觉得好难啊,不过A掉的人不少。我的想法就是类似最小生成树的prim算法,不过这里不再是找与已联通的点集相连的最小边,而是找与某点相连的最小边。这样,只需要找n-1次就可以找到一条将所有点连接起来的单向路径,然后按照题意加上终点到起点的距离就可以了。

#include <bits/stdc++.h>

using namespace std;
struct node
{
    int x,y;
}p[400];
int vis[30];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        int d,l;int n;
        scanf("%d%d",&d,&l);
        scanf("%d%d",&p[0].x,&p[0].y);
        scanf("%d",&n);
        for(int i = 1;i <= n;++i) scanf("%d%d",&p[i].x,&p[i].y);
        int ans = 0;vis[0] = 1;int k = 0;
        for(int i = 1;i <= n;++i)///总共n + 1个点所以循环n次
        {
            int u = 0;
            int maxn = 100000;
            for(int j = 0;j <= n;++j)///找到与k点相连的最短点
            {
                if(!vis[j]&&maxn > abs(p[j].x - p[k].x) + abs(p[j].y - p[k].y))
                {
                    maxn = abs(p[j].x - p[k].x) + abs(p[j].y - p[k].y);
                    u = j;
                }
            }
            if(maxn != 100000)
            {
                vis[u] = 1;
                k = u;
                ans += maxn;
            }
        }
        ans += abs(p[k].x - p[0].x) + abs(p[k].y - p[0].y);
        printf("The shortest path has length %d\n",ans);
    }
    return 0;
}