[2020 Niuke Multi-school] 2020 Niuke Summer Multi-School Training Camp (the third session) D-Points Construction Problem——Construction

D-Points Construction Problem

Ideas

The first point: Never consider a matrix, never consider a matrix, never consider a matrix. Because it can be composed of two, three matrices and several chains, it is too difficult to consider

The most difficult part of this question is the construction of the matrix. Here is an idea to solve this problem.
Of course, this method may not be the most correct, but the result is the best (after all, AC)

Calculate the number of missing edges

This should be relatively simple, that formula (n * 4 - m) / 2results

Matrix-like structure

Here we consider only the non-single-chain structure, namely the structure of the matrix can occur, that is missing the number of sides ≥ 4 missing edge number \ geq 4Lack of loss of edge number4 case

We first give the core part of a matrix, temporarily call it "core".
nuclear
This core has a feature: 4 points can add 4 edges, denoted as: 4 → 4 4 \rightarrow 444

This is the basis of a matrix, and a matrix only needs one core.

Next, the most greedy way is to put down the two blue dots.
23
This structure can add 3 edges with 2 dots, denoted as: 2 → 3 2 \rightarrow 323

Similarly, we can also put this structure on top

23
It is also written as: 2 → 3 2 \rightarrow 323

It is worth noting that: nuclear structure 4 → 4 4 \rightarrow 444 is the premise of all matrix-like structures, but because the number of connected edges is very small, the use of it is reduced as much as possible, that is, the entire graph structure is only used once4 → 4 4 \rightarrow 444 . And2 → 3 2 \rightarrow 323 there is no limit on the number of times, you can go up or right

On the basis of the above figure, we can also propose a structure:
12
this orange point is very clever, it realizes a point and adds two edges, denoted as 1 → 2 1 \rightarrow 212

Obviously, 1 → 2 1 \rightarrow 212 The structure is optimal, the more the structure, the less points can be used to achieve the missing edge requirements. So we need to increase as much as possible1 → 2 1 \rightarrow 212 structure

However, this structure has a quantity limit, and its quantity is subject to 2 → 3 2 \rightarrow 323 quantity limit.

Consider that the structure of the matrix can bring more 1 → 2 1 \rightarrow 212 structure, so we choose to adopt the following greedy strategy

  1. Put a 2 ∗ 2 2*22Matrix of 2
  2. Expand up/right
  3. Use 1 → 2 1 \rightarrow 212 structure filling matrix
  4. Expand right/up
  5. Use 1 → 2 1 \rightarrow 212 structure filling matrix
  6. Repeat 2 − 6 2-626 until all missing edges are satisfied
  7. If the number of points used exceeds that provided, there is no solution, otherwise the excess points will be placed on the far horizon, and then output

Residual dissatisfaction structure

Due to the above strategy, 1 to 2 1 to 2 may be left1 to 2 missing edges, then we can put the point in the lower left corner of the matrix, that is, × in the figure
x
can meet the requirements of one missing edge or two missing edges

AC code

#include <bits/stdc++.h>

using namespace std;

bool flag[60][60];

void print(int n) {
    
    
    if (n < 0) {
    
    
        cout << "No" << endl;
        return;
    }
    cout << "Yes" << endl;
    while (n--)
        cout << n * 100 << " " << n * 100 << endl;
    for (int i = 0; i < 60; ++i)
        for (int j = 0; j < 60; ++j)
            if (flag[i][j])
                cout << i + 1 << " " << j + 1 << endl;
}

void solve() {
    
    
    int T;
    cin >> T;
    for (int ts = 0; ts < T; ++ts) {
    
    
        int n, m;
        cin >> n >> m;
        int target = (n * 4 - m) / 2;
        if ((n * 4 - m) & 1) {
    
    
            n = -1;
            print(n);
            continue;
        }
        memset(flag, 0, sizeof(flag));

        if (target < 4) {
    
    
            int x = 2;
            flag[1][1] = true;
            n--;

            while (target && n >= 0) {
    
    
                flag[x][1] = true;
                x++;
                target--;
                n--;
            }
            print(n);
            continue;
        }
        flag[1][1] = flag[1][2] = flag[2][1] = flag[2][2] = true;
        n -= 4;
        target -= 4;

        int l = 3, r = 3;
        while (target > 2) {
    
    
            // 右扩展
            flag[1][l] = true;
            flag[2][l] = true;
            l++;
            target -= 3;
            n -= 2;

            int len = 3;
            while (len < r && target > 1) {
    
    
                flag[len][l - 1] = true;
                target -= 2;
                n--;
                len++;
            }

            if (target > 2) {
    
    
                // 上扩展
                flag[r][1] = true;
                flag[r][2] = true;
                r++;
                target -= 3;
                n -= 2;

                len = 3;
                while (len < l && target > 1) {
    
    
                    flag[r - 1][len] = true;
                    target -= 2;
                    n--;
                    len++;
                }
            }
        }

        if (target == 2) {
    
    
            n -= 2;
            flag[0][1] = true;
            flag[1][0] = true;
        } else if (target == 1) {
    
    
            n -= 1;
            flag[0][1] = true;
        }
        print(n);
    }
}

signed main() {
    
    
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    int test_index_for_debug = 1;
    char acm_local_for_debug;
    while (cin >> acm_local_for_debug) {
    
    
        if (acm_local_for_debug == '$') exit(0);
        cin.putback(acm_local_for_debug);
        if (test_index_for_debug > 20) {
    
    
            throw runtime_error("Check the stdin!!!");
        }
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    }
#else
    solve();
#endif
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_43448982/article/details/107431908