POJ2965 The Pilots Brothers' refrigerator(枚举)

题目链接

题意:

给出一个4*4矩阵,每个单元要么是 '+', 要么是 '-',每次可以选一个单元,翻转它以及它所在的行和列。求使全部为'-'的最少操作数,并求出操作步骤。

分析:

这题和 1753 类似,但此题的后台数据显然要多余后者。

可以利用打表,算出所有的翻转状态。存入sw。打表代码如下:

int swc(int i) {
    int nsw = 0, j;
    nsw |= (1<<i);

    j = i;
    while(j % 4 != 0) {
        nsw |= (1<<j);
        j--;
    }
    nsw |= (1<<j);

    j = i;
    while((j+1) % 4 != 0) {
        nsw |= (1<<j);
        j++;
    }
    nsw |= (1<<j);

    j = i;
    while(j >= 0) {
        nsw |= (1<<j);
        j -= 4;
    }

    j = i;
    while(j < 16) {
        nsw |= (1<<j);
        j += 4;
    }

    return nsw;
}
View Code

即int sw[16] = {4383, 8751, 17487, 34959, 4593, 8946, 17652, 35064, 7953, 12066,20292, 36744, 61713, 61986, 62532, 63624};

接着直接枚举。 不过要注意的是,如果先入队列,取出时标记,是会TLE的。所以对于新状态要先标记,再放入队列。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>

using namespace std;

const int maxn = (1<<16);
int p[maxn], x[maxn], y[maxn], step[maxn], n;
bool vis[maxn];

int sw[16] = {4383, 8751, 17487, 34959, 4593, 8946, 17652, 35064, 7953, 12066,
    20292, 36744, 61713, 61986, 62532, 63624};

int BFS(int n) {
    memset(p, 0, sizeof(p));
    memset(vis, false, sizeof(vis));
    queue<int> Q;

    Q.push(n);
    step[n] = 0;
    vis[n] = true;

    while(!Q.empty()) {
        int e = Q.front(); Q.pop();

        if(e == 0) return step[e];

        for(int i=0; i<16; i++) {
            int state = e ^ sw[i];
            if(!vis[state]) {
                Q.push(state);
                vis[state] = true;
                p[state] = e;
                x[state] = 4-(i / 4);
                y[state] = 4-(i % 4);
                step[state] = step[e] +1;
            }
        }
    }

    return 0;
}

void print(int s) {
    if(s != n) {
        print(p[s]);
        printf("%d %d\n", x[s], y[s]);
    }
}

int main() {
    n = 0;
    char s[10];

    for(int i=0; i<4; i++) {
        cin >> s;
        for(int j=0; j<4; j++) {
            n <<= 1;
            if(s[j] == '+') n |= 1;
        }
    }

    printf("%d\n", BFS(n));

    print(0);


    return 0;
}
原文地址:https://www.cnblogs.com/tanhehe/p/3138950.html