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) / 2
results
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 number≥4 case
We first give the core part of a matrix, temporarily call it "core".
This core has a feature: 4 points can add 4 edges, denoted as: 4 → 4 4 \rightarrow 44→4
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.
This structure can add 3 edges with 2 dots, denoted as: 2 → 3 2 \rightarrow 32→3
Similarly, we can also put this structure on top
It is also written as: 2 → 3 2 \rightarrow 32→3
It is worth noting that: nuclear structure 4 → 4 4 \rightarrow 44→4 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 44→4 . And2 → 3 2 \rightarrow 32→3 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:
this orange point is very clever, it realizes a point and adds two edges, denoted as 1 → 2 1 \rightarrow 21→2
Obviously, 1 → 2 1 \rightarrow 21→2 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 21→2 structure
However, this structure has a quantity limit, and its quantity is subject to 2 → 3 2 \rightarrow 32→3 quantity limit.
Consider that the structure of the matrix can bring more 1 → 2 1 \rightarrow 21→2 structure, so we choose to adopt the following greedy strategy
- Put a 2 ∗ 2 2*22∗Matrix of 2
- Expand up/right
- Use 1 → 2 1 \rightarrow 21→2 structure filling matrix
- Expand right/up
- Use 1 → 2 1 \rightarrow 21→2 structure filling matrix
- Repeat 2 − 6 2-62−6 until all missing edges are satisfied
- 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
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;
}