UVa 12113 重なり合う正方形 重なり合う正方形のバイナリ表現状態 DFS

質問リンク:重複する正方形
質問の説明:

4 × 4 4\times 4 が与えられた場合4×2 × 2 2\times 2の4 つのグリッド2×2 つの正方形の境界線、 6 6 個まで使用できるかどうかを尋ねる6 2*2 2*222マスが復元されます。5 5
を入力してください5行、各行には10 1010文字、最後の文字は# \##は終了を表し、残りの文字がスペースの場合は、その位置が正方形の境界ではないことを意味します∣ は、正方形の垂直境界を表します (- -は正方形の水平境界を表します。たとえば、次の入力は
ここに画像の説明を挿入します
グラフィックを表します。
ここに画像の説明を挿入します

答え:

各行のターミネータを考慮する必要がないため、入力に含まれる実際の文字数は5 × 9 = 45 5\times 9 = 45 となります。5×9=45なので45 45を使用できます1 1を使用して入力を表す45ビットのバイナリ1は入力位置がエッジであることを示します。たとえば、上の図のステータスは次のように表すことができます:
000000000 000101000 001000100 001101100 000000000 000000000\\000101000\\001000100\\001101100\\0000000000000000000001010000010001000011011006 6
の最大使用により0000000006 つの正方形なので、1 つの正方形、2 つの正方形、3 つの正方形、...、6 つの正方形を使用する可能性のあるすべての状況を事前に列挙し、それらをコレクションに保存することで、各入力に対してのみ対応する状態かどうかを確認するだけです入力がコレクションに表示されます。
同時に、すべての位置に正方形を配置できるわけではなく、本質的に、正方形が 1 つだけ配置された場合、実際には 9 つの状況、つまり 9 9 だけが存在します9 つの位置で四角形を防ぐことができ、四角形になり得る位置を記録できるため、列挙される状態の数を減らすことができます。
特定の場所に正方形を配置した後にバイナリ状態を更新するにはどうすればよいですか? 正方形を配置すると、8 88 つのポジション1 11 (正方形は8 88 の長さは1 11 ) の辺で構成され、同時に4 4障害物があるため、 4 つの位置を0 00 (中央の十字形の 4 つの辺が隠されます)。
正方形の位置に基づいて12 1212ポジションはどうでしょうか?この12 12の左上隅に正方形を配置することを検討できます。12 の位置があるので、これら12 12を変換するだけです。12 の位置に現在の正方形が配置されている位置を加えた値は、 12 12、現在の正方形に対応します。12ポジション。

コード:

#include <bits/stdc++.h>

const int LINE_NUM_EACH_CASE = 5;
const int LINE_LENGTH = 9;
const int MAX_SQUARE_NUM = 6;
const int NUM_SQUARE_POSITION = 9;

using namespace std;

char line[LINE_LENGTH * 2];
long long status;
int maxDepth, caseID;
set<long long> allStatus;
int sidePosition[] = {
    
    1, 3, 9, 13, 18, 19, 21, 22}; // 正方形放在左上角其各个边在二进制中对应的位置
int coverPosition[] = {
    
    10, 11, 12, 20}; // 正方形放在左上角时被挡住的地方
int squarePosition[] = {
    
    0, 2, 4, 9, 11, 13, 18, 20, 22}; // 每个正方形的左上角能在的位置
bool vis[NUM_SQUARE_POSITION]; // 表示某个位置是否已经放过正方形了

void addSquare(int i, long long &status)
{
    
    
    // 八条边的位置变为1
    for (int j = 0; j < 8; j++) {
    
     status |= 1LL << (squarePosition[i] + sidePosition[j]); }
    // 被挡住的地方变为0
    for (int j = 0; j < 4; j++) {
    
     status &= ~(1LL << (squarePosition[i] + coverPosition[j])); }
}

void dfs(int nowDepth, long long nowStatus)
{
    
    
    if (nowDepth == maxDepth) {
    
    
        allStatus.insert(nowStatus);
        return;
    }
    for (int i = 0; i < NUM_SQUARE_POSITION; i++) {
    
     // 枚举正方形可以放置的位置
        if (vis[i]) {
    
     continue; }
        long long tempStatus = nowStatus;
        vis[i] = true;
        addSquare(i, nowStatus);
        dfs(nowDepth + 1, nowStatus);
        nowStatus = tempStatus;
        vis[i] = false;
    }

}

void preprocess()
{
    
    
    for (maxDepth = 0; maxDepth <= MAX_SQUARE_NUM; maxDepth++) {
    
     dfs(0, 0); }
}

bool getInput()
{
    
    
    status = 0;
    for (int i = 0; i < LINE_NUM_EACH_CASE; i++) {
    
    
        cin.getline(line, LINE_LENGTH * 2);
        if (line[0] == '0') {
    
     return false; }
        for (int j = 0; j < LINE_LENGTH; j++) {
    
    
            if (line[j] != ' ') {
    
    
                status |= (1LL << (i * LINE_LENGTH + j)); // 1后面的LL不可以省略
            }
        }
    }
    return true;
}

int main()
{
    
    
    ios::sync_with_stdio(false);
    preprocess();
    while (getInput()) {
    
    
        caseID++;
        cout << "Case " << caseID << ": ";
        if (allStatus.count(status)) {
    
     cout << "Yes" << endl; }
        else {
    
     cout << "No" << endl; }
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/qq_45523675/article/details/129148796