HDU 5613 Baby Ming and Binary image(扫雷地图的还原)

12 篇文章 0 订阅

Baby Ming and Binary image

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 77    Accepted Submission(s): 31
Problem Description
Baby Ming likes to deal with pixel map in the following way:
First, converting the pixel map into binary image (recorded as 01), and then, in the binary figures, for each grid, add up the grid and its neighboring grids’ binary number, and store in matrix <b> Mat </b>.
All the pictures Baby Ming chosen have a <b>blank upper margin and bottom margin</b> (the value of which is 0 in the binary image), because he thinks such a picture is beautiful.
The matrix  Mat  is so big that Baby Ming is worried about the mistakes in the matrix. So he wants to know whether the binary image can be regained according to the  Mat .

 
Input
In the first line contains a single positive integer  T , indicating number of test case.

In the second line there are two numbers  n,m , indicating the size of the binary image and the size of the matrix  Mat

In the next  n  lines, each line input m numbers, indicating the matrix  Mat .

1T30,2<n12,m100
 
Output
Print <b>Impossible</b>, if it is impossible to regain the binary image.

Print <b>Multiple</b>, if it has more than one result.

Otherwise, print the binary image (Baby Ming's 01 matrix)  

Sample Input
  
  
2 4 4 1 2 3 2 2 3 4 2 2 3 4 2 1 1 1 0 3 1 1 1 0
Sample Output
  
  
0 0 0 0 0 1 1 1 0 1 0 0 0 0 0 0 Impossible
Hint
in the second sample, the matrix[1 0 0] is not Baby Ming's Matrix, so there is no answer  

题意:

铭宝宝很喜欢像素图,所以,他喜欢把像素图都做如下的处理:
首先,把像素图变换成二值图(用0101表示),然后,在二值图中,把每个点以及和它相邻的点(最多99个点)的0101值加起来,并保存在一个矩阵Mat中。
铭宝宝选择的图像底边和顶边都是空白的(二值图中值为00),因为他觉得这样的图很漂亮。
不过因为矩阵很大,铭宝宝担心记录过程中出错。所以现在铭宝宝想知道,根据他所保存下来的矩阵Mat,是否能还原出二值图。
题解: 枚举最左边一列的所有 2^{n-2}2n2 种情况,然后递推到右边。因为上下两行不用考虑,所以对于每个枚举,递推过程中格子的状态是唯一的,因此对于每一种枚举判断一下是否能构成符合题意的二值图即可。
#include <bits/stdc++.h>
#define LL long long

using namespace std;

int Mat[110][110],Res[110][110],Tmp[110][110];
int n,m;
void Init(int x)
{
    memset(Tmp, 0, sizeof(Tmp));
    for(int i=1; i<=n; i++)
    {
        Tmp[i][1] = (x % 2);
        x >>= 1;
    }
}
bool Judge()
{
    for(int j=1; j<=m; j++)
    {
        if(j == 1 && (Tmp[1][j] || Tmp[n][j]))
            return false;
        for(int i=1; i<=n; i++)
        {
            if(i == 1)
            {
                int num = Mat[i][j] - Tmp[i+1][j-1] - Tmp[i+1][j];
                if(num == 1 || num == 0)
                    Tmp[i+1][j+1] = num;
                else return false;
            }
            else if(i == n - 1)
            {
                int num = Mat[i][j] - (Tmp[i-1][j-1] + Tmp[i-1][j] + Tmp[i-1][j+1] + Tmp[i][j-1] + Tmp[i][j] + Tmp[i][j+1]);
                if(num != 0)
                    return false;
                Tmp[i+1][j+1] = 0;
            }
            else
            {
                int num = Mat[i][j] - (Tmp[i-1][j-1] + Tmp[i-1][j] + Tmp[i-1][j+1] + Tmp[i][j-1] + Tmp[i][j] + Tmp[i][j+1]
                                       +Tmp[i+1][j-1] + Tmp[i+1][j]);
                if(num == 1 || num == 0)
                    Tmp[i+1][j+1] = num;
                else return false;
            }
        }
    }
    for(int i=1; i<=n; i++)
        if(Tmp[i][m+1]) return false;
    return true;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T-- && scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                scanf("%d",&Mat[i][j]);
        int Cnt = 0;
        for(int i=0; i<(1<<n); i++)
        {
            Init(i);
            if(Judge())
            {
                Cnt++;
                for(int i=1; i<=n; i++)
                    for(int j=1; j<=m; j++)
                        Res[i][j] = Tmp[i][j];
            }
        }
        if(Cnt == 1)
        {
            for(int i=1; i<=n; i++)
                for(int j=1; j<=m; j++)
                    printf(j == m ? "%d\n":"%d ",Res[i][j]);
        }
        else if(Cnt < 1)
            puts("Impossible");
        else
            puts("Multiple");
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值