没有思路,请各位开导一下。

题目描述

小明非常喜欢喝酒,这天小刚把房间里面的酒全部藏起来了。
小明想喝,但又想走最少的路程。
为了简化题目,我们把酒的总数(n)和坐标(x,y)给你,
请你帮小明算出来,从起点(0,0)出发,喝完所有的酒,最少需要走多少米?

输入格式

第一行一个数n (n<=15)

接下来每行2个实数,表示第i杯酒的坐标。

输出格式

一个数,表示要跑的最少距离,保留2位小数。

样例 #1

样例输入 #1

4
1 1
1 -1
-1 1
-1 -1

样例输出 #1

7.41

麻烦给个解释,谢谢。

#include<bits/stdc++.h> 
using namespace std;
struct mp{
    double x,y;
}a[16];                              //用a数组来记录每个点的坐标
int n,t;
double jul[16][16],now,ans=9999999;
bool b[16];
void dfs(int x)
{
    if(now>ans)return;                //剪枝
    if(t==n){
        ans=min(now,ans);
        return;
    }
    for(int i=1;i<=n;i++)
    if(!b[i])
    {
        b[i]=true;
        now+=jul[x][i];
        t++;
        dfs(i);
        b[i]=false;                   //回溯
        now-=jul[x][i];
        t--;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%lf%lf",&a[i].x,&a[i].y);
    a[0].x=0;a[0].y=0;                //好像没用的初始化
    for(int i=0;i<=n;i++)
    for(int j=0;j<=n;j++)
    {
        double x1=a[i].x,x2=a[j].x,y1=a[i].y,y2=a[j].y;
        jul[i][j]=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
        jul[j][i]=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
        //记录i和j之间的距离
    }
    dfs(0);
    printf("%.2f",ans);
    return 0;
}

或者

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int n;
double minl=(1<<31)-1;
bool vis[16];
struct node{
    double x,y;
}a[16];
void dfs(int nowp,double nowl,int step){//(当前所在的点,当前已经走的距离,当前将处理第几个点)
    if(step==n+1&&nowl<minl){//如果step==n+1说明已经有n个点处理完了,即已经遍历完,更新最小距离
        minl=nowl;
    }
    if(nowl>minl){//最优性剪枝
        return;
    }
    for(int i=1;i<=n;i++){
        if(vis[i]==0){
            vis[i]=1;
            dfs(i,nowl+sqrt((a[nowp].x-a[i].x)*(a[nowp].x-a[i].x)+(a[nowp].y-a[i].y)*(a[nowp].y-a[i].y)),step+1);
            vis[i]=0;
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&a[i].y,&a[i].x);
    dfs(0,0,1);
    printf("%.2lf",minl);
    return 0;
}

参考,平面N个点的坐标X和坐标Y求出这些点与点之间的最短距离
https://blog.csdn.net/wyf2017/article/details/105449347

#include<stdio.h>
#include<math.h>
#define N 10

//求两点之间的距离
double distance(double x1, double y1, double x2, double y2) {
return sqrt((x1-x2)(x1-x2)+(y1-y2)(y1-y2));
}
int main() {
double points[N][N];
for(int i=0; i<N; i++) {
printf("第%d个点的横纵坐标",(i+1));
scanf("%lf %lf",&points[i][0],&points[i][1]);
}
int p1 = 0; //p1记录起点,假设起点就是二维数组的第一组元素
int p2 = 1; //p2记录终点,假设终点就是二维数组的第二组元素
double minDistance = distance(points[p1][0], points[p1][1], points[p2][0], points[p2][1]);
for(int i=0; i<N; i++) {
for(int j=i+1; j<N; j++) {
double dist = distance(points[i][0], points[i][1], points[j][0], points[j][1]);
//如果dis的值小于minDistance的值,则更新p1和p2的位置
if(dist < minDistance) {
minDistance = dist;
p1 = i;
p2 = j;
}
}
}

printf("平面内最短距离的两点是:(%.2lf,%.2lf)和(%.2lf,%.2lf)\n",points[p1][0],points[p1][1], points[p2][0], points[p2][1]);
printf("平面内最短距离是:%.2lf",minDistance);

}

最小生成树,用Prim算法

楼上有位兄弟说的是对的,每次走最近,排除用过的,继续走最近,得到的就是最优解
怎么证明的我忘了
这是全路径问题,就不涉及什么算法了,因为每次选择路径都要计算与剩余所有点的距离
除非允许次优解倒有些快速算法

每次都走离他最近的一个点不就行了,比如先拿第一个原点找一个距离最近的(不管是比横纵坐标差还是直接计算距离),然后找到第一个最近点之后计算距离,然后为第一个近点再找下一个近点(记得排除之前用过的点),这样把距离累加下来

这就是动态规划问题