zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    【Anagrams】 cpp
    【Count and Say】cpp
    【Roman To Integer】cpp
    【Integer To Roman】cpp
    【Valid Number】cpp
    重构之 实体与引用 逻辑实体 逻辑存在的形式 可引用逻辑实体 不可引用逻辑实体 散弹式修改
    Maven项目聚合 jar包锁定 依赖传递 私服
    Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
    mysql案例~tcpdump的使用
    tidb架构~本地化安装
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3138950.html
Copyright © 2011-2022 走看看