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: ...... ..***. ..***. ..***. ......
分析:
这是一个DFS的题目,从第一个位置,一个一个往后扫,有两个状态,有雷和没有雷,构成了一棵二叉树。
如果有雷,必须保证周围5个位置的点必须都大于0。
如果没雷,需要保证该位置正上方(x-1)的位置为0。
最后所有填完之后再对所有位置扫一遍,若都为0,则结果正确输出。
代码如下:
#include <stdio.h>
#include <string.h>
char map[25][25];
int dir[5][2]={-1,0,0,1,1,0,0,-1,0,0};
char a[25][25];
int peace;
int n,m;
int check1(int x,int y)
{
for(int i=0;i<5;i++)
{
if(map[x+dir[i][0]][y+dir[i][1]]=='0')
{
return 0;
}
}
return 1;
}
void change(int x,int y)
{//填雷,周围数字改变
for(int i=0;i<5;i++)
map[x+dir[i][0]][y+dir[i][1]]-=1;
}
void rechange(int x,int y)
{//周围数字还原
for(int i=0;i<5;i++)
map[x+dir[i][0]][y+dir[i][1]]+=1;
}
int judge()
{//结束判断是否符合
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(map[i][j]!='0')
return 0;
}
return 1;
}
void dfs(int x,int y,int t)
{
int i,j;
if(peace)
return ;
if(t==n*m+1)
{
if(judge()) //结束判断是否符合
{
peace=1;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
printf("%c",a[i][j]);
putchar('\n');
}
}
return ;
}
int px=t/m+1,py=t%m+1;
if(check1(x,y)) //判断能否填雷
{
change(x,y);
a[x][y]='*';
dfs(px,py,t+1);
rechange(x,y);
}
if(map[x-1][y]=='0' || x==1) //剪枝
{
a[x][y]='.'; //不能填雷
dfs(px,py,t+1);
}
}
int main()
{
int T;
int i,j;
int d=0;
scanf("%d",&T);
while(T--)
{
d++;
memset(map,0,sizeof(map));
memset(a,0,sizeof(a));
for(i=0;i<25;i++)
map[i][0]=map[0][i]='9'; //赋初值
scanf("%d %d%*c",&n,&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%c",map[i]+j);
}
getchar();
}
peace=0;
printf("Case %d:\n",d);
dfs(1,1,1);
}
return 0;
}