UVa 11846 Finding Seats Again Arranging seats DFS Thinking transformation

Question link: Finding Seats Again
Question summary:

Given a number consisting of numbers and . .. (the number must be a single digit). The number represents a surrounding rectangular sub-grid that needs to be filled with the same letters. Your task is to output any set of solutions.

answer:

The first thing that is easy to think of is to consider each number in turn, and then factor this number, so that you can get the length and width of the rectangle, and then consider the position of the rectangle, you can roughly get a code like this: Unfortunately, the
Insert image description here
above The time complexity of the code is too high and it fails the test. The key to the timeout of the above code is that the third loop is too inefficient, and it cannot fully utilize the previous information. For example, in the last round, it was found that some places were filled with letters, and in the next round, considering the position of the matrix, it may be that the positions where the letters were filled in in the previous round were not moved out. This should directly determine that the letters cannot be filled in, and the above code still needs to be looped to judge.
An efficient way is to enumerate directly instead of limiting the size of the rectangle before fixing it. The conditions for the enumerated rectangle to be able to perform the next search are: there is only one number in the rectangle, and the area of ​​the rectangle is equal to this number. Why can this become efficient? First, when we find that there are two numbers in the rectangle, the next enumeration condition can be shrunk: that is, the maximum value of the next column is compressed to the value at the current end. This is because if the next enumeration of the rectangle exceeds There will obviously be two numbers at this location as well. Second, when we find that a position in the rectangle is filled with letters, the maximum value of the column of the rectangle next time should still be the value at the current end. The reason is the same as above. Third, if there is only one number but the value of the number is smaller than the area of ​​the current matrix, we can still change the column limit to the enumeration value of the current column.
The above method can greatly reduce the number of enumeration states, but I can't calculate the specific complexity.

Code:

#include <bits/stdc++.h>

const int MAXN = 20;

using namespace std;

int n, m;
char table[MAXN][MAXN];
char ans[MAXN][MAXN];

void fill(int a, int b, int x, int y, char ch)
{
    
    
    for (int dx = 0; dx < a; dx++) {
    
    
        for (int dy = 0; dy < b; dy++) {
    
    
            ans[x + dx][y + dy] = ch;
        }
    }
}

bool dfs(int id, char ch)
{
    
    
    while (ans[id / n][id % n] != 0) {
    
     id++; }
    if (id == n * n) {
    
     return true; }
    int x = id / n;
    int y = id % n;
    int maxColumn = n;
    for (int a = 1; a + x - 1 < n; a++) {
    
    
        for (int b = 1; b + y - 1 < maxColumn; b++) {
    
    
            if (ans[a + x - 1][b + y - 1] != 0) {
    
    
                maxColumn = b + y - 1; // 当前这一列不行的话,由于a是递增的所以下一次这一列之后没有必要枚举
                break;
            }
            int digitCnt = 0, digit = 0;
            for (int dx = 0; dx < a; dx++) {
    
    
                for (int dy = 0; dy < b; dy++) {
    
    
                    if (isdigit(table[x + dx][y + dy])) {
    
    
                        digitCnt++;
                        digit = table[x + dx][y + dy] - '0';
                        if (digitCnt >= 2) {
    
     break; }
                    }
                }
                if (digitCnt >= 2) {
    
     break; }
            }
            if (digitCnt <= 0 || (digitCnt == 1 && a * b < digit)) {
    
     continue; }
            if (digitCnt >= 2 || (digitCnt == 1 && a * b > digit)) {
    
     // 与上面同样的道理,之后的这一列也不会成立
                maxColumn = b + y - 1;
                break;
            }
            fill(a, b, x, y, ch);
            if (dfs(id, ch + 1)) {
    
     return true; }
            fill(a, b, x, y, 0);
        }
    }
    return false;
}

int main()
{
    
    
    while (cin >> n >> m && n != 0 && m != 0) {
    
    
        memset(ans, 0, sizeof(ans));
        for (int i = 0; i < n; i++) {
    
     cin >> table[i]; }
        dfs(0, 'A');
        for (int i = 0; i < n; i++) {
    
     cout << ans[i] << endl; }
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45523675/article/details/129389592