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

代码

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

原文地址:https://www.cnblogs.com/xuesu/p/10358634.html

时间: 2024-10-13 11:46:03

UVA 11464 - Even Parity 状态压缩,分析 难度: 2的相关文章

uva 11367 dijkstra+dp状态压缩

题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 .1单位汽油可以走1千米  , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 . 解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费. 对于状态的转移时 , 有两种方法: 1.把每个点的所有状态都求出 2.不把每个点的状态都求出 , 而是一单位一单位的加油. 对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就

枚举 UVA 11464 Even Parity

题目传送门 1 /* 2 题意:求最少改变多少个0成1,使得每一个元素四周的和为偶数 3 枚举:枚举第一行的所有可能(1<<n),下一行完全能够由上一行递推出来,b数组保存该位置需要填什么 4 最后检查不同的数量,取最小值 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 using namespace std; 10 11 const int MAXN = 20;

uva 11464 Even Parity(逐层递推)

uva 11464 Even Parity We have a grid of size N x N. Each cell of the grid initially contains a zero(0) or a one(1). The parity of a cell is the number of 1s surrounding that cell. A cell is surrounded by at most 4 cells (top, bottom, left, right). Su

UVA 11464 Even Parity(枚举递推)

11464 - Even Parity Time limit: 3.000 seconds We have a grid of size N x N. Each cell of the grid initially contains a zero(0) or a one(1). The parity of a cell is the number of 1s surrounding that cell. A cell is surrounded by at most 4 cells (top,

uva 818(dfs+图+状态压缩)

题意:有n个环,编号从1到n,给出了一些环环相扣的情况,比如给a和b表示a和b两个环的扣在一起的,每个环都是可以打开的,问最少打开多少个环,然后再扣好,可以让所有的环成为一条链. 题解:状态压缩把所有的打开环的情况枚举出来,然后拿去判断是否成立,更新打开环后的图g[i][j],和每个点的度数,不成立有三种情况,1.计算没有打开的环的度数,如果大于2说明不会有链,2.把没有打开环拿去dfs,访问过就vis[i]++,如果vis[i]>=2说明存在环,3.如果打开的环数num + 1小于链的数量,说

UVA 11008--Antimatter Ray Clearcutting+状态压缩记忆化搜索

题目链接:点击进入 最多只有16个点,如果不用状态压缩的话,最优子结构没法找到.所以我们进行状态压缩,用一个数表示当前的状态,对应二进制位为1表示该位置的树还未被砍掉,为0表示已被砍掉,初始状态为(1< #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 20 #define INF 0x3f3f3f3f typedef struct { i

UVA 1252-Twenty Questions(状态压缩DP+子集枚举)

题目大意:有n个物品,每个物品有m个特征,每个物品的每个特征都可能有或没有,现在假定某个物品,通过询问某些特征来确定这个物品,问最多需要多少次就可以确定物品. 每次询问之后可能根据答案不同来采取不同的进一步询问的策略. 用d[S][S0]表示目前询问了S,得到的回答是S0(即那个物品在S中有S0这些特征),最少还需询问多少次.枚举下一次询问的特征完成递推.最终d[0][0]就是答案.S0显然是S的一个子集.下一次询问的特征不是S已有的特征.如果对于某个d[S][S0]只有一个物品满足,那么此时值

UVA 1633-Dyslexic Gollum(状态压缩DP)

题目大意:求长度为N(1<=N<=400)且不含长度大于或等于K(1<=K<=10)的回文串的01串. 用d[i][j][u]表示长度为i且后11个01串组成数j且不含长度大于或等于u的01串有多少个. 如果j中含有长度至少为u的回文串,那么d[i][j][u]=0. 否则,假设d[i][j][u]可以由d[i-1][v][u]转移得来.根据状态的表示,那么v的低10位肯定是u的高10位,v的最高一位可以为0或1,即v=j/2或v=j/2+(1<<10). 程序将表打出

UVa 11464 Even Parity

题意:给出n*n的01矩阵,将尽量少的0变成1,使得每个元素的上下左右的元素的和为偶数 看的白书的思路,二进制枚举第一行,再依次算出改变元素的个数, 自己写的时候发现这里不会写,“每个元素的上下左右的元素” 大概就是这个意思 真是太捉急了的说-----------5555 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<s