UVa 12113 Cuadrados superpuestos Estado de representación binaria de cuadrados superpuestos DFS

Enlace de pregunta: Cuadrados superpuestos
Descripción de la pregunta:

Dado un 4 × 4 4\times 44×4 cuadrícula en algunos2 × 2 2\times 22×2 límites cuadrados, pregunta si no podemos usar más de6 66 2*2 2*22Se restauran 2 plazas.
Introduzca5 55 filas, cada fila tiene10 1010 caracteres, el último carácter es# \## representa el final. Si los caracteres restantes son espacios, significa que la posición no es el límite del cuadrado. Si es∣ | representa el límite vertical del cuadrado, si es− - representa el límite horizontal del cuadrado. Por ejemplo, la siguiente entrada
Insertar descripción de la imagen aquí
representa el gráfico:
Insertar descripción de la imagen aquí

respuesta:

No necesitamos considerar el terminador de cada línea, por lo que el número real de caracteres contenidos en una entrada es 5 × 9 = 45 5\times 9 = 455×9=45 entonces podemos usar un45 45Binario de 45 bits para representar la entrada, usando1 11 para indicar que la posición de entrada es un borde. Por ejemplo, el estado en la imagen de arriba se puede expresar como:
000000000 000101000 001000100 001101100 000000000 000000000\\000101000\\001000100\\001101100\\000000000000000000000101000001000100001101100000000000
debido al uso máximo de6 66 cuadrados, por lo que podemos enumerar todas las situaciones posibles de uso de un cuadrado, dos cuadrados, tres cuadrados,..., seis cuadrados por adelantado, y luego guardarlos en una colección, de modo que solo para cada entrada Solo verifique si el estado correspondiente a la entrada aparece en la colección.
Al mismo tiempo, no todas las posiciones se pueden colocar con un cuadrado, en esencia, si solo se coloca un cuadrado, en realidad hay nueve situaciones, es decir, solo9 99 posiciones pueden evitar cuadrados. Podemos registrar las posiciones que pueden ser cuadrados, lo que puede reducir el número de estados enumerados.
¿Cómo actualizar el estado binario después de colocar un cuadrado en una ubicación determinada? Después de colocar un cuadrado quedarán8 8La necesidad de 8 puestos se convierte en1 11 (un cuadrado consta de8 88 longitudes son1 1compuesto por lados de 1 ), y al mismo tiempo hay4 4Es necesario cambiar 4 posiciones a 0 0debido a una obstrucción0 (los cuatro lados de la forma de la cruz del medio quedarán oscurecidos). Cómo encontrar rápidamente estos 12 12
según la posición del cuadrado¿Qué pasa con 12 posiciones? Podemos considerar colocar el cuadrado en la esquina superior izquierda de este12 1212 posiciones y luego solo necesitamos convertir estas12 12La posición 12 más la posición donde se coloca el cuadrado actual es 12 12correspondiente al cuadrado actual.12 posiciones.

Código:

#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;
}

Supongo que te gusta

Origin blog.csdn.net/qq_45523675/article/details/129148796
Recomendado
Clasificación