huawei 机试第二题复盘+中行测评第四题

1.矿车采矿问题

已知矿场可以划分成N*M的网格图,每个网格存在地形的差异,因此通过不同网格时成本开销存在差异。
网格有以下5种类型:
1.S为运输起点
2.E为运输终点
3.B为阻塞点,不允许通行,
4.C为检查点,矿车在运输路经中,至少需要进入一次检查点。
5.标志为数字的网格,其数字表示经过该网格的成本开销。
运输矿车只能上下左右4个方向运行。注意可重复进入网格。
寻求一条从S网格到E网格,并至少经过一次的检查点的最低成本运输路径,并输出其成本开销。

例如输入:
3 3
S 4 5
7 B 3
C 9 E
输出:16

-----

输入:
3 4
12 B S 13
7 C 4 7
8 3  10 E
输出:15

思路:C为必经点那结果一定是S->C最短+C->E最短 迪杰斯特拉算法

import java.util.*;
public class Main
{
	public static void main(String[] args) {
	    Scanner in=new Scanner(System.in);
    	int n=in.nextInt();
    	int m=in.nextInt();
        in.nextLine();
    	String[][] matrix =new String[n][m];
    	for(int i=0;i<n;i++){
            matrix[i]=in.nextLine().split(" ");
    	}
    	int[][] graph=new int[n][m];
    	int startX = -1, startY = -1, endX = -1, endY = -1,midX=-1,midY=-1;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                String str=matrix[i][j];
                if (str.equals("S")) {
                    startX = i;
                    startY = j;
                    graph[i][j]=0;
                } else if (str.equals("E")) {
                    endX = i;
                    endY = j;
                    graph[i][j]=0;
                }else if(str.equals("C")){
                    midX = i;
                    midY = j;
                    graph[i][j]=0;
                }else if(str.equals("B")){
                    graph[i][j]=Integer.MAX_VALUE;
                }else{
                    graph[i][j]=Integer.parseInt(str);
                }
            }
        }
    	
        int left=findMinCostPath(graph,startX,startY,midX,midY);
        int right=findMinCostPath(graph,midX,midY,endX,endY);
        if(left==0||right==0){
            return 0;
        }else{
            System.out.println(left+right);
        }


        in.close();
		
	}
	public static int findMinCostPath(int[][] graph,int startX,int startY,int endX,int endY) {
        int rows = graph.length;
        int cols = graph[0].length;
        int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

        int[] cost = new int[rows*cols];
        
        Arrays.fill(cost,Integer.MAX_VALUE);
        
        cost[startX*cols+startY] = 0;

        PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] nums1,int[] nums2){
                return nums1[2]-nums2[2];
            }
        });
        queue.offer(new int[]{startX, startY,0});

        while (!queue.isEmpty()) {
            int[] curr = queue.poll();
            int x = curr[0];
            int y = curr[1];
            int d = curr[2];

            if(x==endX&&y==endY){
                return cost[endX*cols+endY];
            }
            for (int i=0;i<4;i++) {
                int nx = x + dirs[i][0];
                int ny = y + dirs[i][1];

                if (nx >= 0 && nx < rows && ny >= 0 && ny < cols&&(d+graph[nx][ny]<cost[nx*cols+ny])) {
                    int newCost = cost[x*cols+y] + graph[nx][ny];
                    cost[nx*cols+ny] = newCost;
                    queue.offer(new int[]{nx, ny,newCost});
                    
                }
            }
           
        }
         return 0;
    }
}

2.类似零钱兑换

假设有很多不同面额的货币,每个货币只可以使用1次,但可以用不同面额的货币加在一起来购买大面额的商品,但是不想找零,因此对于一些金额的商品,无法进行购买。
比如有 1、2、5 元的货币,我可以购买 了 3元的商品(1+2) ,但是由于5 元无法找零,因此无法购买4元的商品。现给定一个长度为n的正整数数组 money,分别表示n个货币的金额,求出无法购买的商品最小价格。

import java.util.*;

public class Main
{
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int n=in.nextInt();
		int[] nums=new int[n];
		int sum=0;
		for(int i=0;i<n;i++){
		    nums[i]=in.nextInt();
		    sum+=nums[i];
		}
		int[] dp=new int[sum+1];
		int max=Integer.MAX_VALUE;
		for(int i=0;i<=sum;i++){
		    dp[i]=max;
		}
		//01背包问题 先物品再背包
		dp[0]=0;
		for(int i=0;i<n;i++){
		    for(int j=sum;j>=nums[i];j--){
		        if(dp[j-nums[i]]!=max){
		            dp[j]=Math.min(dp[j],dp[j-nums[i]]+1);
		        }
		    }
		}
		for(int i=0;i<=sum;i++){
		    if(dp[i]==max){
		        System.out.println(i);
		        return;
		    }
		}
		System.out.println(sum+1); 
	}
	
}

java在线编程        GDBOnline

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值