问题描述
zsyzgu是一个弱菜,尽管如此他还是参加了智能体系列赛。智能体系列赛的问题经简化后是这样的,有一只猴子和一些矿点,知道他们在平面上的坐标,这只猴子要经过这些矿点至少一次。假设这只猴子从点A走到点B所要花费的步数是这两个点的曼哈顿距离(即|A.x-B.x|+|A.y-B.y|),问这只猴子经过这些矿点至少一次所需的最少步数。
系列赛中的许多选手都用了贪心的策略,即每次都到最近的没经过的矿点去。但zsyzgu的思路是搜索,这也是他能够摆脱垫底命运获得纪念版T-shirt的原因。
输入格式
第一行两个数表示猴子的坐标;
第二行一个数n表示矿点数;
接下来n行每行两个数表示每个矿点的坐标。
输出格式
一行一个数表示最少步数。
样例输入
0 0
4
0 1
0 2
0 3
0 -2
样例输出
7
数据规模和约定
这里是引用
对于100%的数据:1<=n<=10,横纵坐标都是整数,其的绝对值<=10000。
分析与思路
这题的N数据比较小我们可以用全排列矿点的顺序再去逐一判断最小的路径
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class Main {
//矿坐标
static List<int[]> l;
//矿开采顺序
static List<Integer> l2;
//猴子坐标
static int[] m;
//记录矿是否被开采过
static boolean[] b;
//最短路径
static int min;
public static void main(String[] args) {
l=new LinkedList();
l2=new LinkedList();
Scanner sc=new Scanner(System.in);
m=new int[]{sc.nextInt(),sc.nextInt()};
//矿点数
int n=sc.nextInt();
b=new boolean[n];
//初始化最小值
min=Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
l.add(new int[]{sc.nextInt(),sc.nextInt()});
}
//对矿点全排列搜索
dfs(n,0);
System.out.println(min);
}
static void dfs(int n,int dex) {
//排列完成开始判断;
if(dex>=n) {
f();
return;
}
for(int i=0;i<n;i++) {
//如果没有被开采
if(!b[i]) {
b[i]=true;
l2.add(i);
dfs(n,dex+1);
//回溯
b[i]=false;
l2.remove(l2.size()-1);
}
}
}
static void f() {
//当前起始点
int x=m[0];
int y=m[1];
//路径
int s=0;
for(int i=0;i<l2.size();i++) {
int[] xy=l.get(l2.get(i));
s+=Math.abs(x-xy[0])+Math.abs(y-xy[1]);
x=xy[0];
y=xy[1];
}
min=Math.min(s, min);
}
}
评测
这题感觉学会使用全排列的惯用模板再逐一判断哪个排列的路径最小就可以了