题目
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
代码
#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