SDUT 2410 Mine Number 2012年山东省第三届ACM大学生程序设计竞赛题

23 篇文章 0 订阅

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值