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個商品:
*   每個商品:容量(正負,爲負表示可以增加揹包容量) 、利益(正負)
*
* 現在選擇商品裝到揹包,使總利益最大
* */
明天繼續!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章