2020/9/1拼多多笔试

  1. 第一题
/*
* 题目描述
* ------------
* |  2 | 1
* |3   |   8
* |-----------
* |4   |   7
* |  5 | 6
* |-----------
* 有一个NxN的矩阵,把里面的(i,j)划分都上述8个区域,米字处(横竖中线、斜线)为0
*
* */
import java.util.Scanner;
public class Main1 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        scanner.close();

        int [][] arr = new int[n][n];
        double mid = (n-1)/2.0;//中线
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                //23
                if (i< mid && j<mid ){
                    if (i<j) arr[i][j] = 2;
                    else if (i>j)arr[i][j] = 3;
                }
                //45
                else if (i>mid && j<mid ){
                    if (n-1-i>j)arr[i][j]=4;
                    else if (n-1-i<j)arr[i][j]=5;
                }
                //18
                else if (i<mid && j>mid ){
                    if (n-1-i>j)arr[i][j]=1;
                    else if (n-1-i<j)arr[i][j]=8;
                }
                //67
                else if (i>mid && j>mid ){
                    if (i>j)arr[i][j]=6;
                    else if (i<j)arr[i][j]=7;
                }
            }
        }

        for (int i = 0; i <n ; i++) {
            for (int j = 0; j <n-1 ; j++) {
                System.out.print(arr[i][j]);
                System.out.print(" ");
            }
            System.out.println(arr[i][n-1]);
        }
    }
}

/*
示例:
input: 10
output:
0 2 2 2 2 1 1 1 1 0
3 0 2 2 2 1 1 1 0 8
3 3 0 2 2 1 1 0 8 8
3 3 3 0 2 1 0 8 8 8
3 3 3 3 0 0 8 8 8 8
4 4 4 4 0 0 7 7 7 7
4 4 4 0 5 6 0 7 7 7
4 4 0 5 5 6 6 0 7 7
4 0 5 5 5 6 6 6 0 7
0 5 5 5 5 6 6 6 6 0
* */
  1. 第二题
/**
 * 题目描述
 * 有一个NxM矩阵,矩阵有值只有0和1, 1代表一个人,相邻的人(只包含上下左右相邻)为一组。
 * 现在请移动其中一个人,移动后使一个团队的人数尽可能大,求这个最大的值。
 * 如:
 * 4 4
 * 1 0 1 1
 * 1 1 0 1
 * 0 0 0 0
 * 1 1 1 1
 *
 * 可以把(0,2)移动到(2,0):
 * 4 4
 * 1 0 0 1
 * 1 1 0 1
 * 1 0 0 0
 * 1 1 1 1
 * 形成一个8人的组,是所有移动方案中最大的。
 *
 * 我的解题思路是:
 *   设置一个最大组人数值max,对于每一个0位置,尝试将该位置置1,然后以该位置为入口dfs进入改组,计算人数,更新max,
 *   dfs遍历的同时会将该组全部置-1。再次dfs把-1还原为1。
 *   尝试将所有0变为1后,会得到更新后的max,这个max可能需要-1:
 *         如果移动后只有一组,那个这个移动的元素是内部移动,不能从其他组来,所以需要-1
 *         判断方式: dfs把最大组置-1,然后访问整个数组,如果还存在1,说明多个组,返回max;否则,返回max-1
 */
public class Main2 {
    private int[][] arr;
    private int row;
    private int col;

    public Main2() {
        Scanner scanner = new Scanner(System.in);
        row = scanner.nextInt();
        col = scanner.nextInt();
        arr = new int[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = scanner.nextInt();
            }
        }
        scanner.close();

        int max = 0; //最大组人数
        int maxi = 0, maxj = 0; //记录最大组的一个元素下标
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j] == 0) {
                    arr[i][j] = 1; //尝试把0的地方填1
                    int num = dfs(i, j,arr); //dfs遍历得到该组的人数,同时会将改组全部变为-1
                    if (num > max) {
                        max = num; //更新最大值
                        maxi = i; //更新最大组入口元素下标
                        maxj = j;
                    }
                    recover(i, j,arr); //把该组从-1还原为1
                    arr[i][j] = 0; //还原该位置的0
                }
            }
        }

        dfs(maxi, maxj,arr); //从入口访问最大组,将该组全部置-1

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (arr[i][j]==1){  //还有其他元素是1,表明现在不止一个组,那么那个填充1的0位置,可以是其他组移动过来的
                    System.out.println(max);
                    return;
                }
            }
        }
        //上面没有返回,说明移动后只有一个组,移动的这个元素也属于本组,于是需要减出来。
        System.out.println(max-1);
    }


    //从[i,j]处进入一个组,统计其人员数,并在访问过程中全部置-1;
    int dfs(int i, int j, int[][]arr) {
        if (i < 0 || i >= arr.length || j < 0 || j >= arr[0].length || arr[i][j] == 0 || arr[i][j] == -1) return 0;
        arr[i][j] = -1;
        return 1 +
                dfs(i, j + 1,arr) +
                dfs(i, j - 1,arr) +
                dfs(i - 1, j,arr) +
                dfs(i + 1, j,arr);
    }
    //从[i,j]处进入一个组, 访问全组,将dfs改变的-1还原为1
    void recover(int i, int j,int arr[][]) {
        if (i < 0 || i >= arr.length || j < 0 || j >= arr[0].length || arr[i][j] !=-1) return;
        arr[i][j] = 1;
        recover(i, j + 1,arr);
        recover(i, j - 1,arr);
        recover(i - 1, j,arr);
        recover(i + 1, j,arr);
    }


    public static void main(String[] args) {
        Main2 main = new Main2();
    }
}
/*
示例:
input:
4 4
1 0 1 1
1 0 1 1
0 1 0 0
1 1 1 1
output:
12
*/
  1. 第三题
/*
* 题目描述:
* 输入一个数N,大小为M的数组Arr。
* 对于一个数X,如果X能被Arr中的某个数整除,则成X是‘特殊的’
* 对于1~N,判断其中有多少数是‘特殊的’
*
* 可以直接暴力,如下,但是会超时。
* 使用一些优化方法:
* 1. 记录数组中的最大、小值,1~N遍历时 从最小值开始,到最大值时结束。
* 2. 遍历1~N时可以判断是否是素数。
* 3. 不知道还有没有其他优化方法或者更好的解法???
* */
public class Main4 {
    private int M;
    private int N;
    private int[] arr;

    public Main4() {
        Scanner scanner = new Scanner(System.in);
        N = scanner.nextInt();
        M = scanner.nextInt();
        arr = new int[N];
        for (int i = 0; i < M; i++) {
            arr[i] = scanner.nextInt();
        }
        scanner.close();
        int res = 0;
        for (int i = 1; i <= N; i++) {
            for (int a : arr) {
                if (i % a == 0) {
                    res++;
                    break;
                }
            }
        }

        System.out.println(res);
    }
}
  1. 第四题
/*
* 题目描述
* 背包问题:初始背包容量M
* 有N个商品:
*   每个商品:容量(正负,为负表示可以增加背包容量) 、利益(正负)
* 现在选择商品装到背包,使总利益最大
 * 这题是01背包问题的改编。
 * 01背包问题中商品的体积全部是正,这里可以是负数,表示增大背包空间
* */
posted @ 2020-09-01 22:07  Edwin_Xu  阅读(170)  评论(0编辑  收藏  举报