题解 蓝桥杯 算法提高 ADV-1179 智能体系列赛 Java(全排列 DFS)

问题描述

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);
	}
	
}

评测

在这里插入图片描述

这题感觉学会使用全排列的惯用模板再逐一判断哪个排列的路径最小就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值