uva 11464

分类: 枚举 和 剪枝

题意: 给定矩阵由0,1组成,使用最少的改变(使0变成1),使得任何元素的上下左右元素(如果存在)和为偶数

输入: 测试组数, 矩阵大小n ,矩阵每一个数

输出: 最小翻转次数,无法实现则输出-1

 

解法: 

         类似关灯问题,枚举第一行的状态(2^n)种情况,依题意,所有的后续方格可以由上面确定,检查翻转次数与是否满足

         关键在于如何编写,即按照顺序确定每一个方格的状态

         在代码中体现为 check函数,注意实现过程中适当剪枝,提高速度

#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
using namespace std;

///宏定义
const int  INF = 990000000;
const int MAXN = 30;
const int maxn = MAXN;
///全局变量 和 函数
int A[maxn][maxn], B[maxn][maxn];
int n;
int check(int s)
{
    memset(B, 0, sizeof(B));
    int cnt = 0;
    for (int i = 0; i < n; i++)
    {
        if (s & (1 << i))
            B[0][i] = 1;
        else if (A[0][i] == 1)
            return INF;
    }
    for (int i = 1; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int sum = 0;
            if (i > 1)
                sum += B[i - 2][j];
            if (j > 0)  //注意边界取值
                sum += B[i - 1][j - 1];
            if (j < n - 1) //注意边界取值
                sum += B[i - 1][j + 1];
            B[i][j] = sum % 2;
            if (B[i][j] == 0 && A[i][j] == 1)
                return INF;
        }
    }
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (A[i][j] != B[i][j])
                cnt++;
        }
    }
    return cnt;
}

int main()
{
    ///变量定义
    int T;
    int cases = 1;
    scanf("%d", &T);
    while (T--)
    {
        memset(A, 0, sizeof(A));
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                scanf("%d", &A[i][j]);
            }
        }
        
        //枚举第一行
        int ans = INF;
        for (int i = 0; i < (1 << n); i++)
        {
            int cnt = check(i);
            ans = min(ans, cnt);
        }
        if (ans == INF)
            ans = -1;
        printf("Case %d: %d\n", cases++, ans);
    }


    ///结束
    return 0;
}

 

posted on 2013-09-17 20:35  小书包_Ray  阅读(129)  评论(0编辑  收藏  举报

导航