恒邪

Mine Number(搜索,暴力) ACM省赛第三届 G

Mine Number

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

 

Every one once played the game called Mine Sweeping, here I change the rule. You are given an n*m map, every element is a '*' representing a mine, or a '.' representing any other thing. If I ask you what's the total number of mines around (i, j), you should check (i, j)'s up, down, left, right and also itself (if overstep the boundary, ignore it), if that position is a '*', you should add one to the total number of (i, j), and here I call the number Mine Number. For example, if the map is "..**.. ", we can get the Mine Number as "012210" easily, but here is the question, if I give you the Mine Number, can you tell me the original map?

 

输入

The input consists of multiple test cases.
The first line contains a number T, representing the number of test cases.
Then T lines follow. For each case, the first line contains two numbers n and m (1<=n, m<=20).representing the lines and rows. Then following n lines, each line contain m numbers each number represents the Mine Number.

输出

For each case, please print the case number (beginning with 1) and the original map which you reverted. The data guarantee there is only one result.

示例输入

2
7 11
10010100101
21223221222
32354532323
32355532323
31235321333
21022201333
10001000111
5 6
001110
013431
014541
013431
001110

示例输出

Case 1:
...........
*..*.*..*.*
*.*****.*.*
*.*****.*.*
*..***..*.*
*...*...***
...........
Case 2:
......
..***.
..***.
..***.
......

提示

 

来源

2012年"浪潮杯"山东省第三届ACM大学生程序设计竞赛

饭稀

 赛题重现是遇到此题,比赛是觉得挺麻烦,虽然有了思路,但并没有拿出时间来做。比赛过后,做了一下,代码还是比较容易写的,只是一直WA,自认为明明已经完美的代码就是不给过,最后发现一个让我想撞墙的问题,输出的地图中没有空格,我的输出即使在美观,亦不会AC的。
正确答案是这样的:
...........
*..*.*..*.*
*.*****.*.*
*.*****.*.*
*..***..*.*
*...*...***
...........
 
而我的答案是这样滴:
. . . . . . . . . . .
* . . * . * . . * . *
* . * * * * * . * . *
* . * * * * * . * . *
* . . * * * . . * . *
* . . . * . . . * * *
. . . . . . . . . . .

懒得吐槽了,讲一下这道题吧,就是类似扫雷的规则,相信大家都比较熟悉扫雷,只是题中矩阵的数字表示上下左右和中(就是数字所在位置)五个位置中雷的个数。给出要求输入数字矩阵输出唯一确定的符合数字矩阵的图形矩阵'*'表示雷,'.'表示安全。

看似题目要求从数字矩阵推出图形矩阵,我们亦可以认为是要收缩符合已知数字矩阵的图形矩阵,矩阵的每个点只有两种状态(. or *),用搜索实现起来便不是很难。

注意:输入数字数组时要用字符形式存入字符数组中。

货不多说,下面看代码

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 using namespace std;
  5 char mapp[25][25];
  6 char num[25][25];
  7 int n,m,dx[5]={0,-1,1,0},
  8         dy[5]={1,0,0,-1};
  9 bool ispos;
 10 bool isout(int x,int y)//判断是否出界
 11 {
 12     if( x<0||x>=m)
 13         return 0;
 14     if(y<0||y>=n)
 15         return 0;
 16     return 1;
 17 }
 18 void print(void)//输出字符数组
 19 {
 20     int i,j;
 21     for(i=0; i<m; ++i)
 22     {
 23         for(j=0; j<n; ++j)
 24             printf("%c ",mapp[i][j]);
 25         printf("\n");
 26     }
 27 }
 28 /*void printn(void)
 29 {
 30     int i,j;
 31     for(i=0; i<m; ++i)
 32     {
 33         for(j=0; j<n; ++j)
 34             printf("%c ",num[i][j]);
 35         printf("\n");
 36     }
 37 }*/
 38 int  prints()//判断最后一行是否全为零
 39 {
 40     int j;
 41     for(j=0; j<n; ++j)
 42         if(num[m-1][j]!='0')
 43             return 0;
 44     return 1;
 45 }
 46 void dfs(int x,int y)
 47 {
 48    // cout<<x<<' '<<y<<endl;
 49    // cout<<"--------------"<<endl;
 50    // printn();
 51    // print();
 52     if(ispos)
 53         return;
 54     if(x==m&&y==0)
 55     {
 56         if(prints())
 57         {
 58             ispos=true;
 59             print();
 60         }
 61         return;
 62     }
 63     int xx,yy,k,falg=1;
 64     for(k=0;k<=4;++k)//判断四周是否有0,
 65     {
 66         xx=x+dx[k];
 67         yy=y+dy[k];
 68         if( isout(xx,yy) && num[xx][yy]=='0' )
 69         {
 70             falg=0;//标记周围有0,不能不为'*'
 71             break;
 72         }
 73     }
 74 
 75     if(falg)//没有标记,则可以放地雷
 76     {
 77         if(isout(x-1,y)&&num[x-1][y]!='1')//若上方不唯1,则前面填错,需回溯
 78             return;
 79         mapp[x][y]='*';
 80         for(k=0;k<=4;++k)//若放地雷,周围标记地雷数-1
 81         {
 82             xx=x+dx[k];
 83             yy=y+dy[k];
 84             if( isout(xx,yy))
 85                     num[xx][yy]--;
 86         }
 87         if(y==n-1)
 88             dfs(x+1,0);
 89         else
 90             dfs(x,y+1);
 91         for(k=0;k<=4;++k)//周围标记地雷数+1恢复
 92         {
 93             xx=x+dx[k];
 94             yy=y+dy[k];
 95             if(isout(xx,yy))
 96                 num[xx][yy]++;
 97         }
 98     }
 99      mapp[x][y]='.';
100      if(isout(x-1,y)&&num[x-1][y]!='0')//若上方不唯0,则前面填错,需回溯
101             return;
102   if(y==n-1&&!ispos)
103         dfs(x+1,0);
104     else if(!ispos)
105         dfs(x,y+1);
106 }
107 int main()
108 {
109     int i,test,t_num;
110     cin>>test;
111     for(t_num=1;t_num<=test;++t_num)
112     {
113         cin>>m>>n;
114         for(i=0;i<m;++i)
115             scanf("%s",num[i]);
116         printf("Case %d:\n",t_num);
117         ispos=0;
118         dfs(0,0);
119     }
120     return 0;
121 }

 

posted on 2014-04-28 11:07  恒邪  阅读(265)  评论(0编辑  收藏  举报

导航