Blue Bridge Cup Day13 java group pruning

Posted by squizz on Tue, 15 Feb 2022 11:01:07 +0100

Violence laws are often inefficient and waste time on many unnecessary calculations.

Pruning is a metaphor: to "cut off" branches that will not produce an answer or are unnecessary. The key to pruning lies in the judgment of pruning: what to cut and where to cut. Pruning is a common optimization method in search, which can often optimize the exponential complexity to the complexity of approximate polynomial.

  • The main pruning technology of BFS is weight judgment. If there is a repeated state when searching a certain layer, prune it.
  • DFS has many pruning technologies, including feasible pruning, optimal pruning, search order pruning, eliminating equivalent redundancy, memory search, etc

  1. Feasibility pruning: check the current status. If the current condition is illegal, it will not continue and return directly
  2. Search order pruning: the search tree has multiple levels and branches. Different search orders will produce different search tree forms, and the complexity is also very different.
  3. Optimality pruning: in the search process of optimization problem, if the current cost has exceeded the previous optimal solution, then this search has no significance to continue. At this time, stop backtracking the search of the current branch.
  4. Eliminate equivalent redundancy: if the final results of different branches are the same, it is enough to search only one branch.
  5. Memory search: in the process of recursion, many branches are calculated repeatedly, which will greatly reduce the execution efficiency of the algorithm. With memory search, the calculated results are saved, and the results are directly taken out when needed in the future to avoid repeated operation, so as to improve the efficiency of the algorithm. Memory search is generally in DP.

Question 1 sum of squares

sample input

12

sample output

0 2 2 2

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int i = 0, j = 0, k = 0, l = 0;
        int x = scanner.nextInt();
        for (i = 0; x >= i * i; i++) {
            for (j = i; x >= i * i + j * j; j++) {
                for (k = j; x >= i * i + j * j + k * k; k++) {
                    for (l = k; x >= i * i + j * j + k * k + l * l; l++) {
                        if (i * i + j * j + k * k + l * l == x) {
                            System.out.println(i + " " + j + " " + k + " " + l);
                            return;
                        }
                    }
                }
            }
        }
    }
}

Question 2 cut the grid

Output description

In all solutions, the partition containing the upper left corner may contain the smallest number of lattices.

sample input

3 3
10 1 52
20 30 1
1 2 3

sample output

3
import java.util.Scanner;

public class Main {
    public static int[][] map;
    public static int[][] visited;
    public static int m;
    public static int n;
    public static int sum = 0;
    public static int min = 999999;
    public static int[][] direction = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        m = scanner.nextInt();
        n = scanner.nextInt();
        map = new int[1000][1000];
        visited = new int[1000][1000];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                map[i][j] = scanner.nextInt();
                visited[i][j] = 0;
                sum = sum + map[i][j];
            }
        }
        dfs(0, 0, 0, 1);
        System.out.println(min);
    }

    public static void dfs(int x, int y, int temp, int k) {
        temp = temp + map[x][y];
        if (temp * 2 > sum) {
            return;
        }

        if (temp * 2 == sum) {
            if (k < min) {
                min = k;
            }
            return;
        }
        visited[x][y] = 1;
        for (int i = 0; i < direction.length; i++) {
            int x1 = x + direction[i][0];
            int y1 = y + direction[i][1];
            if (x1 >= m || y1 >= n) {
                continue;
            }
            if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && visited[x1][y1] == 0) {
                dfs(x1, y1, temp, k+1);
            }
        }
        visited[x][y] = 0;
    }
}

It's too slow to write. It's too delicious.  

The third question is the mystery of the path

sample input

4
2 4 3 4
4 3 3 3

sample output

0 4 5 1 2 3 7 11 10 9 13 14 15

import java.util.Scanner;
import java.util.Stack;

public class Main {
    private static int n = 0;
    private static int[] north;
    private static int[] west;
    private static int[][] map;
    private static int[][] direction = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private static int[][] visited;
    private static Stack<Node> stack = new Stack<Node>();
    private static int temp = 0;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        north = new int[n];
        west = new int[n];
        map = new int[n][n];
        visited = new int[n][n];
        for (int i = 0; i < n; i++) {
            north[i] = scanner.nextInt();
        }
        for (int i = 0; i < n; i++) {
            west[i] = scanner.nextInt();
        }
        int temp = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                map[i][j] = temp;
                visited[i][j] = 0;
                temp++;
            }
        }
        dfs(0, 0);
    }

    private static void dfs(int x, int y) {
        west[x]--;
        north[y]--;
        visited[x][y] = 1;
        int flag = 0;
        if (temp == 1) {
            return;
        }
        if (west[x] < 0 || north[y] < 0) {
            west[x]++;
            north[y]++;
            visited[x][y] = 0;
            return;
        }
        if (x == n - 1 && y == n - 1) {
            for (int i = 0; i < n; i++) {
                if (west[i] != 0 || north[i] != 0) {
                    flag = 1;
                    break;
                }
            }
            if (flag != 1) {
                temp = 1;
                Node node = new Node(x, y, map[x][y]);
                stack.push(node);
                int[] a = new int[stack.size()];
                for (int i = stack.size() - 1; !stack.isEmpty(); i--) {
                    a[i] = stack.pop().value;
                }
                for (int i = 0; i < a.length; i++) {
                    System.out.print(a[i] + " ");
                }
                return;
            }
        }
        Node node = new Node(x, y, map[x][y]);
        stack.push(node);
        for (int i = 0; i < direction.length; i++) {
            int nx = x + direction[i][0];
            int ny = y + direction[i][1];
            if (nx >= 0 && nx < n && ny >= 0 && ny < n && visited[nx][ny] == 0) {
                dfs(nx, ny);
            }
        }
        if (!stack.isEmpty()) {
            stack.pop();
        }
        visited[x][y] = 0;
        west[x]++;
        north[y]++;
    }
}

class Node {
    int x;
    int y;
    int value;

    Node(int x, int y, int value) {
        this.x = x;
        this.y = y;
        this.value = value;
    }
}

722 deep searches before pruning and 54 deep searches after pruning

Question 4 examination room

sample input

5
8
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5

sample output

import java.util.*;

public class Main {
    private static int n;
    private static int m;
    private static int ans = 10000;
    private static int[][] relation;
    private static Map<Integer, List<Integer>> map = new HashMap<>();

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        relation = new int[n + 1][n + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                relation[i][j] = 0;
            }
        }
        for (int i = 0; i < m; i++) {
            int a1 = scanner.nextInt();
            int a2 = scanner.nextInt();
            relation[a1][a2] = 1;
            relation[a2][a1] = 1;
        }
        List<Integer> list = new ArrayList<>();
        list.add(1);
        map.put(0, list);
        dfs(1);
        System.out.println(ans);
    }

    public static boolean checked(int i, int k) {
        for (int j = 0; j < map.get(i).size(); j++) {
            if (relation[k][map.get(i).get(j)] == 1 || relation[map.get(i).get(j)][k] == 1) {
                return false;
            }
        }
        return true;
    }

    public static void dfs(int k) {
        System.out.println("DFS");
        if (k == n + 1) {
            ans = Math.min(ans, map.size());
            return;
        }
        if (map.size() >= ans) {
            return;
        }
        for (int i = 0; i < map.size(); i++) {//Traverse each examination room

            if (checked(i, k)) {//Check the i-th examination room
                map.get(i).add(k);
                dfs(k + 1);
                map.get(i).remove(map.get(i).size() - 1);//Remove the last element of the collection
            }

            /*int flag = 0;
            List<Integer> list = map.get(i);

            for (int j = 0; j < list.size(); j++) {//Traverse each person in each examination room
                int temp = list.get(j);
                if (relation[k][temp] == 1 || relation[temp][k] == 1) {//It matters
                    flag = 1;
                    break;
                }
            }

            if (flag == 0) {
                list.add(k);//No one in examination room i has anything to do with k. add k to examination room i
                dfs(k + 1);
                list.remove(list.size() - 1);
                break;//The traversal of each examination room can be completed
            }

            if (i == map.size()) {//At the last cycle, a new examination room is created
                List<Integer> list1 = new ArrayList<>();
                list1.add(k);//Add the k th student to the collection
                map.put(map.size(), list1);//Add the newly created examination room to the examination room
                dfs(k + 1);
                map.remove(map.size() - 1);
            }*/
        }

        List<Integer> list = new ArrayList<>();
        list.add(k);
        map.put(map.size(), list);
        dfs(k + 1);
        map.remove(map.size() - 1);

    }

}

Pure ghost problem

For the k-th student, even if he can join a classroom, he should be at the end of each dfs (). Build a new examination room for him to try. It's easy to write if you want to understand this.

Question 5 fourth order magic square

  1  2 15 16
 12 14  3  5
 13  7 10  4
  8 11  6  9

And:

  1 12 13  8
  2 14  7 11
 15  3 10  6
 16  5  4  9

It can be regarded as two different schemes.

public class Main {
    private static int[][] map;
    private static int count = 0;
    private static int[] a = {9999, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

    public static void main(String[] args) {
        map = new int[5][5];
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                map[i][j] = 0;
            }
        }
        map[1][1] = 1;
        dfs(2, 16);
        System.out.println(count);
    }

    private static void dfs(int s, int t) {
        //System.out.println("DFS");
        if (s == 5 && map[1][1] + map[1][2] + map[1][3] + map[1][4] != 34) {
            //System.out.println(map[1][1] + " " + map[1][2] + " " + map[1][3] + " " + map[1][4]);
            return;
        }
        if (map[1][1] + map[1][2] + map[1][3] + map[1][4] == 34) {
            //System.out.println(map[1][1] + " " + map[1][2] + " " + map[1][3] + " " + map[1][4]);
        }
        if (s == 9 && map[2][1] + map[2][2] + map[2][3] + map[2][4] != 34) {
            return;
        }
        if (s == 13 && map[3][1] + map[3][2] + map[3][3] + map[3][4] != 34) {
            return;
        }
        if (s == 14 && map[1][1] + map[2][1] + map[3][1] + map[4][1] != 34) {
            return;
        }
        if (s == 14 && map[1][4] + map[2][3] + map[3][2] + map[4][1] != 34) {
            return;
        }
        if (s == 15 && map[1][2] + map[2][2] + map[3][2] + map[4][2] != 34) {
            return;
        }
        if (s == 16 && map[1][3] + map[2][3] + map[3][3] + map[4][3] != 34) {
            return;
        }
        if (s == 17 && map[1][4] + map[2][4] + map[3][4] + map[4][4] == 34 && map[1][1] + map[2][2] + map[3][3] + map[4][4] == 34 && map[4][1] + map[4][2] + map[4][3] + map[4][4] == 34) {
            count++;
            return;
        }

        for (int i = s; i <= t; i++) {
            swap(i, s);
            for (int j = 2; j <= 16; j++) {
                if (j % 4 != 0) {
                    map[j / 4 + 1][j % 4] = a[j];//assignment
                } else {
                    map[j / 4][4] = a[j];
                }
            }
            dfs(s + 1, t);
            swap(s, i);
        }
    }

    private static void swap(int i, int s) {
        int temp;
        temp = a[i];
        a[i] = a[s];
        a[s] = temp;
    }
}

The answer is 416 kinds, and the 16 numbers are arranged in full order. I don't know if there is something wrong with the pruning of which piece

Topics: Java