UVA 11464 - Even Parity 状态压缩,分析 难度: 2

题目

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2459


题意

N*N 的01方阵,可用操作为把任意0变为1,求操作的最小次数,使得任意位置的上下左右之和(不包含自身)为偶数

 

思路

如刘书,关键在于状态只有第一行的2^15个。

 

感想

1. 忘了memset

 

代码

UVA 11464 - Even Parity 状态压缩,分析 难度: 2
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <tuple>
#include <cassert>

using namespace std;
#define LOCAL_DEBUG
#define NOW_QUEUE (ques[queId])
#define LAST_QUEUE (ques[1 - queId])
const int MAXN = 15;
struct Node{
    int lineSta;
    int lineSum;
    int changed;
    Node(int _lineSta, int _lineSum, int _changed) {
        lineSta = _lineSta;
        lineSum = _lineSum;
        changed = _changed;
    }
};
queue<Node> ques[2];
int queId;
int orgStatus[MAXN][MAXN];
int stackedStatus[MAXN];
int statusLimit;

int getLineSum(int formerlineSta, int lineSta) {
    return (formerlineSta ^ (lineSta >> 1) ^ (lineSta << 1)) & statusLimit;
}

int getChanged(int lineno, int lineSta) {
    int changedSta = stackedStatus[lineno] ^ lineSta;
    int changed = 0;
    while (changedSta > 0) {
        changed++;
        changedSta -= (changedSta & (-changedSta));
    }
    return changed;
}


int main() {
#ifdef LOCAL_DEBUG
    freopen("input.txt", "r", stdin);
    //freopen("output2.txt", "w", stdout);
#endif // LOCAL_DEBUG
    int T;
    scanf("%d", &T);
    for (int ti = 1; ti <= T; ti++) {
        queId = 0;

        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            stackedStatus[i] = 0;
            for (int j = 0; j < n; j++) {
                scanf("%d", orgStatus[i] + j);
                stackedStatus[i] = stackedStatus[i] * 2 + orgStatus[i][j];
            }
        }

        statusLimit = (1 << n) - 1;
        for (int sta = 0; sta <= statusLimit; sta++) {
            if((sta & stackedStatus[0]) == stackedStatus[0])NOW_QUEUE.push(Node(sta, getLineSum(0, sta), getChanged(0, sta)));
        }
        for (int i = 1; i < n; i++) {
            queId = 1 - queId;
            while (!LAST_QUEUE.empty()) {
                Node node = LAST_QUEUE.front(); LAST_QUEUE.pop();
                Node newNode(node);
                newNode.lineSta = stackedStatus[i];
                int lastLineSum = node.lineSum ^ stackedStatus[i];
                bool fl = true;
                for (int j = 0; j < n && fl; j++) {
                    if (lastLineSum & (1 << j)) {
                        if (stackedStatus[i] & (1 << j)) { fl = false; break; }
                        else {
                            newNode.lineSta |= 1 << j;
                        }
                    }
                }
                if (fl) {
                    newNode.lineSum = getLineSum(node.lineSta, newNode.lineSta);
                    newNode.changed = node.changed + getChanged(i, newNode.lineSta);
                    NOW_QUEUE.push(newNode);
                }
            }
        }
        int ans = n * n + 1;
        while (!NOW_QUEUE.empty()) {
            Node node = NOW_QUEUE.front(); NOW_QUEUE.pop();
            ans = min(ans, node.changed);
        }
        if (ans > n * n)printf("Case %d: -1\n", ti);
        else printf("Case %d: %d\n", ti, ans);
    }

    return 0;
}
View Code

 

上一篇:Mysql报错[Warning] TIMESTAMP with implicit DEFAULT value is deprecated和Buffered warning: Changed limit


下一篇:【练手】ansible搭建zookeeper