题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2410
Mine Number
题目意思很简单,玩过扫雷的人都能秒懂,可是实施起来,却不容易呀!!!首先对第一行进行枚举,不冲突即可,其他行:上一行为0,此行不能放雷,上一行为1,此处进行枚举,不冲突即可。而且有几个很坑的地方,我就不多说了,代码有备注,自己看吧。。。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,flag;
char mine[25][25],aa[25][25];
int dx[]={0,-1,0,1,0},dy[]={0,0,-1,0,1};
int a[25][25];
bool outmap(int x,int y)
{
if(x<0||x>=n||y<0||y>=m)
return true;
return false;
}
void down(int x,int y) //该点是雷,周围减1
{
int i,xx,yy;
for(i=0;i<5;i++)
{
xx=x+dx[i];
yy=y+dy[i];
if(!outmap(xx,yy))
a[xx][yy]--;
}
}
void up(int x,int y) //该点不是雷,周围加1
{
int i,xx,yy;
for(i=0;i<5;i++)
{
xx=x+dx[i];
yy=y+dy[i];
if(!outmap(xx,yy))
a[xx][yy]++;
}
}
int check2(int x,int y) //判断周围是否符合条件
{
int i,xx,yy;
for(i=0;i<5;i++)
{
xx=x+dx[i];
yy=y+dy[i];
if(!outmap(xx,yy))
if(a[xx][yy]<=0)
return 0;
}
return 1;
}
int check3()
{
int i;
for(i=0;i<m;i++)
if(a[n-1][i]!=0)
return 0;
return 1;
}
void print()
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
printf("%c",mine[i][j]);
printf("\n");
}
}
void dfs(int x,int y)
{
if(flag)
return;
if(x==n)
{
if(check3())
{
flag=1;
print(); //经过,我无数次的实验,貌似print()这个输出不放在这个位置就会一直wrong。。。
//我在想会不会有没有符合情况的没有输出呀。。。
}
return ;
}
if(y==m)
{
dfs(x+1,0);
return;
}
if(x==0) // 首先对第一行进行枚举,不冲突即可
{
if(check2(x,y))
{
mine[x][y]='*';
down(x,y);
dfs(x,y+1);
up(x,y);
}
mine[x][y]='.';
dfs(x,y+1);
}
else
{
if( a[x-1][y]==0 ) // 上一行为0,此行不能放雷
{
mine[x][y]='.';
dfs(x,y+1);
}
else if( a[x-1][y]==1 ) // 上一行为1,此处进行枚举,不冲突即可
if( check2(x,y) )
{
mine[x][y]='*';
down(x,y);
dfs(x,y+1);
up(x,y);
}
}
}
int main()
{
int T,t=1;
scanf("%d",&T);
while(T--)
{
int i,j;
flag=0;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
scanf("%s",aa[i]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
a[i][j]=aa[i][j]-'0';
printf("Case %d:\n",t++); //尼玛,真不想吐槽,放在dfs(0,0)后就一直wrong...
dfs(0,0);
}
return 0;
}