阿里20.3.25笔试题第一题

阿里20.3.25笔试题第一题 (动态规划,类似于路径搜索思想)

题目描述

给定一个行数为3,列数为col的矩阵B,比如
5 10 5 4 4
1 7 8 4 0
3 4 9 0 3
从每一列中选择一个数,得到一个一行col列的一维数组,求该一维数组中每相邻两个数之差的绝对值的累加和的最小值
比如这里就是5 7 5 4 4,所以输出是5

输入描述
四行输入
第一行输入为数组的列数n;
第二至四行输入一个3*col的矩阵a,每行输入col个正整数。

输出描述
一行一个正整数表示答案

思路分析

  • 首先是输入的部分,首先接收输入一个正整数n, 再建立一个二维数组来存放输入矩阵,行数为3,列数为n。双层循环遍历用输入给数组赋值。
  • 这题的思路首先想到类似于路径搜索,在矩阵中从最左列开始选择一条路径,一列一列地走到最右列(其中每一列只能走一次),最终的结果是求这条路径,使其满足路径上的元素相邻元素的差值的绝对值累加和最小。因此想到用动态规划。
  • 选择二维数组来存储元素 (i,j) 的状态dp[i][j],定义为选择元素 (i,j) 作为路径的终点,此时对应的结果为res,因此最终的结果应该为遍历i=1,2,3 res=Math.min(dp[i][col-1]) ;
  • 状态转移方程:
    点(i,j)的状态dp[i][j]应该等于路径中前一个点(即为前一列所选择的数) (k,j-1)再加上点(i,j)与(k,j-1)的差值的绝对值,因此
    dp[i][j]=Math.abs(array[i][j]-array[k][j-1])+dp[k][j-1]);
    此处,由于本列选择的数是第i行,但前一列选择的数不一定是哪一行,记为第k行,因此遍历k=0,1,2, 选择Math.abs(array[i][j]-array[k][j-1])+dp[k][j-1]) 的最小值。
  1. 最终结果返回遍历i 获得的最小值dp[i][col-1]。

易错点

  1. 二维数组循环输入赋值,先遍历行,再遍历列
  2. 动态规划的部分,此题是整列的规划,先遍历列,在固定第j列的时候遍历了行i,在固定了(i,j)的时候再遍历前一点的k。因此,内外循环是先j 其次i 最后k,顺序不能改变。
//阿里20.3.25笔试题第一题  (动态规划,类似于路径搜索)
import java.util.Scanner;
import java.util.Arrays;

public class Main5 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int  col= in.nextInt();
        int[][] array = new int[3][col];
        //二维数组的输入
        for (int i = 0; i<3; i++) {//此处i与j调换位置也会出错
            for (int j=0;j<col;j++) {
                array[i][j] = in.nextInt();
            }
        }
        int [][] dp=new int[3][col];//动态规划 整列规划

        for (int i = 0; i < 3; i++) {
            Arrays.fill(dp[i],0);//初始化
            dp[i][0] = 0;
        }
        for(int j=1;j<col;j++)//此处注意若i与j调换位置,就不对了
        {
            for(int i=0;i<3;i++)
            {
                dp[i][j]=Math.abs(array[i][j]-array[0][j-1])+dp[0][j-1];
                for(int k=1;k<3;k++)
                {
                    dp[i][j]=Math.min(dp[i][j],Math.abs(array[i][j]-array[k][j-1])+dp[k][j-1]);

                   /* dp[i][j]=Math.min(Math.abs(array[i][j]-array[0][j-1])+dp[0][j-1],
                    Math.min(Math.abs(array[i][j]-array[1][j-1])+dp[1][j-1],
                    Math.abs(array[i][j]-array[2][j-1])+dp[2][j-1]));*/
                }
            }
        }
           int res=dp[0][col-1];
        for(int i=0;i<3;i++)
        {
            res=Math.min(res,dp[i][col-1]);
        }
          // int res=Math.min(dp[0][col-1],Math.min(dp[1][col-1],dp[2][col-1]));

           System.out.println(res);
        }

    }

(PS: 笔试时有了思路,但是一方面卡在了输入输出,一方面卡在了当前点的前一点(k,j) 这里的k是遍历求最小值来确定 ,所以还是要多做动态规划的题呀~)

你可能感兴趣的:(阿里20.3.25笔试题第一题)