题目
首先输入一个(n,k)的值,其中n构成一个n*n的二维数字,而二维数字具体的参数则是1-k某一具体的值。问题是要找到遍历1…k这些所有值经过的最短路径。但是如果输入的二维数组缺少从0-k的某个值时,那么就没有最短路径。路径的求法是:比如aij和bij的路径是|ai-bi|+|aj-bj|。
思路:
1、输入部分就不多说了,做好之后建议输入输出测试一下,方便只有的调试。
2、关于找出最短路径的问题,刚开始想可以用回溯用递归,加上没有最短路径的问题,结果思路就很乱。于是就选择最简单最直接的这种方法。
首先,要找到从1…k所经过的最短路径,此时应该判断该二维数组应该包含从1-k的所有值,该条件成立之后才能找最短路径。
对于找1-k的最短路径,就是找1->2的最短路径、2->3的最短路径、3->4的最短路径…对他们求和,求出来的就是最短路径。
找1->2的最短路径的最短路径时,考虑到出现1和2的数组位置是变化的,很难动态的找出谁是最短路径,所以就把出现过1和2的所有数组都保存下来,最后在求出距离最小的。
在考虑求保存出现数组下标i、j时最开始出现了一个错误的想法,因为保存的是两个元素,所以很容易选择了hashmap,但是输出结果时就发现少了不少元素,当key相同时,hashmap会更新值,所以最后选择数组保存就OK了。
最后对保存的元素相减求最小值。
下面直接上代码了。
import java.util.*;
/**
* 功能描述
* 最短路径问题
* @author Newton
* @date 2021/4/5 10:14
* @Version 1.0
*/
public class meituan {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int k=in.nextInt();
int[][] nums = new int[n][n];
//输入数组
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
nums[i][j]=in.nextInt();
}
}
int sum=0;
//找出相邻两个k之间的最短距离
for (int i = 1; i < k; i++) {
int flag=0;
flag=test1(n,i,i+1,nums);
if (flag==-1){
System.out.println("无法到达");
}
else{
sum=sum+flag;
System.out.println("从"+i+"->"+(i+1)+",最短路劲为:"+flag);
}
}
System.out.println("最短路劲为:"+sum);
}
//找出相邻两个k之间的最短距离并返回最短距离
public static int test1(int n,int a,int b,int[][] nums){
//把找到的相邻两个key之间的所有元素放在hashmap中,如果为空则不满足条件
//【思路更正】最开始的思路是上面的,但是hashmap不满足提议,因为相同key的时候会替换,所有把他们分别放到数组中,基数为i,偶数为j
List<Integer> listai=new ArrayList<>();
List<Integer> listaj=new ArrayList<>();
List<Integer> listbi=new ArrayList<>();
List<Integer> listbj=new ArrayList<>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (nums[i][j]==a){
listai.add(i);
listaj.add(j);
}
if (nums[i][j]==b){
listbi.add(i);
listbj.add(j);
}
}
}
int min=abs((listai.get(0)-listbi.get(0)))+abs((listaj.get(0)-listbj.get(0)));
int len=0;
//如果hashmap为空说明缺少k,返回-1
if(listai.size()==0 || listaj.size()==0){
return -1;
}
//找出从a->b的最短距离
else{
for (int i = 0; i < listai.size(); i++) {
int ai=listai.get(i);
int aj=listaj.get(i);
// System.out.println("ai:"+ai+" aj:"+aj);
for (int j = 0; j < listbi.size(); j++) {
int bi=listbi.get(j);
int bj=listbj.get(j);
// System.out.println("bi:"+bi+" bj:"+aj);
len=abs((ai-bi))+abs((aj-bj));
// System.out.println(len);
min=(min<=len)? min: len;
// System.out.println(min);
}
}
return min;
}
}
public static int abs(int a) {
return (a < 0) ? -a : a;
}
}
运行结果:
代码其实还有改进的空间,比如输入元素的判断等等,大家可以自行改进。