Blue Bridge Cup AcWing learning notes 4-2 simulated learning (with relevant Blue Bridge real questions: wrong ticket, moving distance, date problem, flight time, takeout priority) (Java)

Students who participate in the blue bridge cup can pay attention to the blogger. The blogger is also preparing the Blue Bridge Cup and can brush questions with the blogger's blog.

Blue Bridge Cup

My AcWing

The title and pictures are from the counseling class of group ab of Blue Bridge Cup C + +

simulation

According to the operation given by the topic, use the code to describe it in turn.

Simulation is generally some very basic topics, but don't underestimate simulation. Seemingly simple operations may have unexpected situations.

Simulation needs to be careful! Be sure to take all the circumstances into account.

Examples

AcWing 466. Palindrome date

Enumeration + simulation

Most date problems can be solved by simulation.

This question is to judge whether the date is a palindrome string in a certain range.

Enumerate the palindromes of the year, and then judge whether the month and date are legal.

① Enumerate only the first four digits
② Judge whether it is within the range
③ Then judge whether the last four digits are legal

Time complexity O ( 1 0 4 ) O(10^4) O(104) enumeration 1 0 4 10^4 104 numbers. The amount of calculation to judge whether each number is legal is constant, so the total amount of calculation is O ( 1 0 4 ) O(10^4) O(104)

import java.util.Scanner;

public class Main {

    static int[] days = new int[]{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Number of days per month in a normal year

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int date1 = sc.nextInt();
        int date2 = sc.nextInt();
        int res = 0;
        for (int i = 1000; i < 10000; i++) {
            int date = i, x = i; // data and x are the first four digits
            for (int j = 0; j < 4; j++) { // Turn the data over and put it behind the data
                date = date * 10 + x % 10;
                x /= 10;
            }
            // At this time, the palindrome string of the year has been simulated. Next, as long as the date is within the range and whether the month and date are legal
            if (date1 <= date && date <= date2 && check_valid(date)) res++;
        }
        System.out.println(res);
    }

    private static boolean check_valid(int date) {
        int year = date / 10000;
        int month = date % 10000 / 100;
        int day = date % 100;
        if (month == 0 || month > 12) return false;
        // Normal year judgment
        if (day == 0 || month != 2 && day > days[month]) return false;
        // Judge leap year
        if (month == 2) {
            int leap = 0; // 0 indicates a normal year and 1 indicates a leap year
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) leap = 1;
            if (day > 28 + leap) return false;
        }
        return true;
    }
}

The fourth 2013 Blue Bridge Cup

AcWing 1204. Wrong note

Java group A / b question 7

What this problem needs to deal with is input. It only gives us the number of lines and does not give us the number of elements in each line. We can't just use Scanner class to read in. We can use BufferedReader to read in. When there is a lot of data, we can also use this class to optimize the reading in. See the code for details.

simulation

Time complexity O ( N ) O(N) O(N)

Open a Boolean array st[] to record whether the number has appeared. If so, it is marked as true; When traversing, if the state of the number has been marked as true, it indicates that the number is a duplicate sign; We can find the maximum and minimum values during the first traversal. If the state of the number from small to large is false, it indicates that the number is a hyphen.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    static int N = 100010;
    static boolean[] st = new boolean[N]; // The tag status defaults to false

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(in.readLine());
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        int res1 = 0; // Broken sign
        int res2 = 0; // Duplicate sign
        while (n-- > 0) {
            String[] nums = in.readLine().split(" ");
            for(int i = 0; i < nums.length; i++) {
                int t = Integer.parseInt(nums[i]);
                max = Math.max(max, t); // Maximum found
                min = Math.min(min, t); // Find minimum value
                if (st[t]) res2 = t; // If the previous value is true, the duplicate number is found
                st[t] = true;
            }
        }
        for (int i = min ; i <= max ; i ++) {
            if (!st[i]) res1 = i; // If the status is false, a hyphen is found
        }
        System.out.println(res1 + " " + res2);
    }
}

sort

Time complexity O ( N l o g N ) O(NlogN) O(NlogN)

Sort all numbers, and judge the double sign elements and broken sign elements according to the subscript of the array.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {

    static final int N = 100010;
    static int[] a = new int[N];

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(in.readLine());
        int index = 0;
        while (n-- > 0) {
            String[] nums = in.readLine().split(" ");
            for (int i = 0; i < nums.length; i++) {
                a[index++] = Integer.parseInt(nums[i]);
            }
        }
        Arrays.sort(a, 0, index);
        int res1 = 0; // Broken sign
        int res2 = 0; // Duplicate sign
        for(int i = 1; i < index; i++) {
            if (a[i] == a[i - 1]) res2 = a[i]; // Duplicate sign
            else if (a[i] == a[i - 1] + 2) res1 = a[i] - 1; // Broken sign
        }
        System.out.println(res1 + " " + res2);
    }
}

Real topic of the 6th 2015 Blue Bridge Cup

AcWing 1219. Moving distance

JavaA/C group question 8

Manhattan distance d ( i , j ) = ∣ x i − x j ∣ + ∣ y i − y j ∣ d(i,j)=|x_{i}-x_{j}|+|y_{i}-y_{j}| d(i,j)=∣xi​−xj​∣+∣yi​−yj​∣

The numbers in the matrix are arranged in a serpentine shape, and the difficulty is to find the coordinates of the numbers. We can learn from the two-dimensional array and reduce all the numbers in the matrix to - 1, so as to find our line number:

The original coordinate of 1 is (1, 1), now it is (0, 1). The line number of 1: 1 / 6 = 0. Let these two numbers be n and m, w is the width of the line, and the line number: n / w, m / w

How to find the column number? Let's take a look at the two-dimensional array with normal sorting:

Column No.: n% w, M% w

But the problem is serpentine, that is, all odd rows. We should flip the coordinates. Here's a special judgment.

simulation

Time complexity O ( 1 ) O(1) O(1)

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int w = sc.nextInt();
        int m = sc.nextInt() - 1;
        int n = sc.nextInt() - 1; // The starting position starts from 0 to facilitate the calculation of row and column coordinates

        int x1 = m / w, x2 = n / w; // Line number
        int y1 = m % w, y2 = n % w; // Column number
        if (x1 % 2 != 0) y1 = w - 1 - y1; // Special judgment on odd sequence, flip y coordinate
        if (x2 % 2 != 0) y2 = w - 1 - y2;

        System.out.print(Math.abs(x1 - x2) + Math.abs(y1 - y2)); // Manhattan distance formula
    }
}

Real topic of the 8th 2017 Blue Bridge Cup

AcWing 1229. Date issue

JavaB group question 7

Enumeration + simulation

We enumerate all numbers between 19600101 and 20591231: ① judge whether it is legal; ② judge whether it may be a given representation

import java.util.Scanner;

public class Main {

    static int[] days = new int[]{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Number of days per month in a normal year

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        String[] data = str.split("/");
        int a = Integer.parseInt(data[0]);
        int b = Integer.parseInt(data[1]);
        int c = Integer.parseInt(data[2]);

        for (int date = 19600101; date <= 20591231; date++) {
            int year = date / 10000;
            int month = date % 10000 / 100;
            int day = date % 100;
            if (check_valid(year, month, day)) {
                if (year % 100 == a && month == b && day == c ||    // Year / month / day
                    month == a && day == b && year % 100 == c ||    // Month / day / year
                    day == a && month == b && year % 100 == c) {    // Day / month / year
                    System.out.printf("%d-%02d-%02d\n", year, month, day); // Remember to add '-' to the formatted output
                }
            }
        }
    }

    private static boolean check_valid(int year, int month, int day) {
        if (month == 0 || month > 12) return false;
        if (day == 0 || month != 2 && day > days[month]) return false;
        if (month == 2) {
            int leap = 0;
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) leap = 1;
            if (day > 28 + leap) return false;
        }
        return true;
    }
}

True topic of the 9th 2018 Blue Bridge Cup

AcWing 1231. Flight time

Java group a question 6

When flying from Beijing to the Middle East, we don't know the time difference with the Middle East, but let's first sort out the formula of flight time: first, when the plane flies from Beijing to the Middle East, the landing time minus the take-off time also needs to add the time difference: end1 - start1 + time. When the plane flies back to Beijing from the Middle East, the landing time minus the take-off time also needs to subtract the time difference: end2 - start2 - time, What we are looking for is the flight time of the plane. Because the flight time of the plane back and forth is the same, we can add the flight time back in the future: end1 - start1 + end2 - start2. We find that the time difference is offset, so this question has nothing to do with the time difference. The flight time of the plane: $t = (end1 - start1 + end2 - start2) / 2$

The formula has been introduced. The next thing to deal with is the input and output of string.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    public static void main(String[] args) throws IOException {
        String[] input = in.readLine().split(" ");
        int n = Integer.parseInt(input[0]);
        while (n-- > 0) {
            int time = (get_time() + get_time()) / 2;
            int hour = time / 3600, minute = time % 3600 / 60, second = time % 60;
            System.out.printf("%02d:%02d:%02d\n", hour, minute, second);
        }
    }

    private static int get_time() throws IOException {
        String[] line = in.readLine().split(":| "); // Separating: and spaces
        
        int d = 0;
        if (line.length == 7) d = line[6].charAt(2) - '0'; // If the length is 7, it means that there is (+ n) after the string. Remember to turn it to int

        int h1 = Integer.parseInt(line[0]);
        int m1 = Integer.parseInt(line[1]);
        int s1 = Integer.parseInt(line[2]);
        int h2 = Integer.parseInt(line[3]);
        int m2 = Integer.parseInt(line[4]);
        int s2 = Integer.parseInt(line[5]);

        return get_seconds(h2, m2, s2) - get_seconds(h1, m1, s1) + d * 24 * 3600;
    }
    
    // Convert all time into seconds from 00:00:00 of the day
    private static int get_seconds(int h, int m, int s) {
        return h * 3600 + m * 60 + s;
    }
}

True topic of the 10th 2019 Blue Bridge Cup

AcWing 1241. Take out priority

JavaB group question 7

Analyze the first example:

Finally, at time 6, only takeout 2 is in the priority cache, and the answer is output 1.

Violent enumeration (memory overrun)

Time complexity O ( N 2 ) O(N^2) O(N2)

Enumerate take out orders at each time

AcWingMLE, 7 out of 10 data, 90 out of 100 in the Blue Bridge Cup. The last data memory exceeded the limit, but it was also a considerable score.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt(), t = sc.nextInt();
		// Array definition saves memory in global variables
        int[][] a = new int[t + 1][n + 1]; // Order i is the time and j is the delivery number
        int[] p = new int[n + 1]; // priority

        for (int i = 0; i < m; i++) a[sc.nextInt()][sc.nextInt()]++;

        for (int i = 1; i < t + 1; i++) {
            for (int j = 1; j < n + 1; j++) {
                if (a[i][j] > 0) {
                    a[i][j] = a[i - 1][j] + a[i][j] * 2; // Add the priority of this order
                    if (a[i][j] > 5)
                        p[j] = 1; // Prioritize takeout at this time
                } else {
                    if (a[i - 1][j] > 0) {
                        a[i][j] = a[i - 1][j] - 1;
                        if (a[i][j] <= 3)
                            p[j] = 0;
                    }
                }
            }
        }

        int res = 0;
        for (int i = 0; i < p.length; i++) res += p[i];

        System.out.println(res);
    }
}

optimization

The time when we get the order from each takeout is discrete. It may take a long time before there is a second order. In fact, we can compress the middle part and unify the continuous period of time without order to the next time when there is an order, or put it at time T:

The advantage of this is that we only need to consider the stores with orders when we go to do every moment, and we don't need to consider the stores without orders.

At this time, we can sort all orders in chronological order without enumerating the time, and process a batch of the same orders each time. As long as the time point of the order is the same as the store id, we will regard it as one.

score[i] indicates the current priority of the ith store

last[i] indicates the last time there was an order in the ith store

st[i] indicates whether the ith store is currently in the priority cache

Pseudo code

Content before processing t time:

In this way, the time when there is no order in the middle can be compressed:

score[id] -= t - last[id] - 1; // If there are orders at the 3rd and 6th times, the time when things are not sold should be 4 and 5, so it is necessary to reduce one 6-3-1 = 2

There are also two judgments:

if (score[id] < 0) score[id] = 0;
if (score[id] <= 3) st[id] = false; // Remove priority cache

Update last: last[id] = t

Content of processing t time:

score[id] += cnt * 2; // Add priority
if (score[id] > 5) st[id] = true; // Put in priority cache

There may be no orders in each store in the last period of time. We also need to calculate how long we haven't sold anything between last[id] ~ T in the last period of time:

for (int i = 1; i <= n; i++) {
	if (last[i] < T) {
        score[i] -= T - last[i]; // - 1 is not needed at this time, because there is no order at time T
		if (score[i] <= 3) st[i] = false;
    }
}

Obtained results:

int res = 0;
for (int i = 1; i <= n; i++) {
	if (st[i]) res++;
}
sout(res);

Complete code

import java.util.Scanner;
import java.util.Arrays;

public class Main {

    static final int N = 100010;
    static int[] score = new int[N]; // Store priority
    static int[] last = new int[N]; // Last time there was an order
    static boolean[] st = new boolean[N]; // Indicates whether the store is in the priority cache
    static PII[] order = new PII[N]; // order

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt(), T = sc.nextInt();
        for (int i = 0; i < m; i++) order[i] = new PII(sc.nextInt(), sc.nextInt());
        Arrays.sort(order, 0, m);

        for (int i = 0; i < m;) { // Cycle to find the same order
            int j = i;
            while (j < m && order[j].ts == order[i].ts && order[j].id == order[i].id) j++;
            int t = order[i].ts, id = order[i].id;
            int cnt = j - i; // Quantity of orders in the same batch
            i = j;

            // Process information before time t
            score[id] -= t - last[id] - 1; // There is no order quantity in the middle
            if (score[id] < 0) score[id] = 0;
            if (score[id] <= 3) st[id] = false; // Remove priority cache

            // Processing information at time t
            score[id] += cnt * 2; // Add priority
            if (score[id] > 5) st[id] = true; // Put in priority cache

            last[id] = t;
        }

        for (int i = 1; i <= n; i++) {
            if (last[i] < T) {
                score[i] -= T - last[i]; // - 1 is not needed at this time, because there is no order at time T
                if (score[i] <= 3) st[i] = false;
            }
        }

        int res = 0;
        for (int i = 1; i <= n; i++) if (st[i]) res++;

        System.out.println(res);
    }

    static class PII implements Comparable<PII> {
        int ts;
        int id;

        public PII(int ts, int id) {
            this.ts = ts;
            this.id = id;
        }
        
        @Override
        public int compareTo(PII o) {
            if(this.ts > o.ts)  return 1;
            if(this.ts == o.ts) {
                if (this.id > o.id) return 1;
                return -1;
            }
            return -1;
        }
    }
}

If you don't understand the code, you can comment below

Keywords: Java Algorithm Simulation

Added by phant0m on Wed, 09 Mar 2022 06:42:04 +0200