原题链接:Minesweeper
解题思路:
分析这个问题,可以得到:整个雷区内的地雷块占少数,而安全块占多数;
通常思路为:看一块是不是地雷,不是的话,查找以它为中心矩形区域的地雷数,存入这一块;
这个方法,倒过来看,用地雷,去炸以它为中心的矩形区域内的非地雷区域,每次被炸的块加1,也就是把输出的数字,看作是被炸的次数;
得到以下总思路:
1.输入雷区的范围;
2.输入雷区存入一个二维字符数组,在输入同时,把不是雷区的字符数组赋值为' 0 ',表示未被炸;
3.循环调用函数轰炸(若此块不是地雷,没办法轰炸周围非地雷区域,返回)否则轰炸以它为中心的矩形区域内的非地雷区域,被轰炸的块加1,即表示被轰炸次数加1;
为什么说这种方法极其高效:
雷块始终是占少数,如图
* * . . .
. . . . .
. * . . .
常规思路的话,需要调用12 次函数体;
如图:


反常规思路:

#include<stdio.h>
void bombing(int x,int y);
int X,Y,M,N=0;
int num=1;
char b[100][100];
/*-------------------------------------------------------------*/
int main()
{
while(scanf("%d%d",&X,&Y)&&!(X==0&&Y==0))
{
for(int i=0;i<X;i++)
{
getchar(); /*clear data buffer cache*/
for(int j=0;j<Y;j++)
{
scanf("%c",&b[i][j]);
if(b[i][j]=='.')
b[i][j]='0';
}
}
N++; /*the token of field;*/
for(int i=0;i<X;i++)
for(int j=0;j<Y;j++)
bombing(i,j);
printf("Field #%d:\n",N);
for(int i=0;i<X;i++)
for(int j=0;j<Y;j++)
{printf("%c",b[i][j]);if((j+1)%Y==0)printf("\n");}
printf("\n");
}
}
/*-------------------------------------------------------------*/
void bombing(int x,int y)
{
if(b[x][y]!='*')
return ;
/*-------------------------------------------------------------*/
y+=1; /*up square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
/*-------------------------------------------------------------*/
y-=2; /*down square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
y+=1; /*back to start square*/
/*-------------------------------------------------------------*/
x+=1; /*right square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
/*-------------------------------------------------------------*/
x-=2; /*left square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
x+=1; /*back to start square*/
/*-------------------------------------------------------------*/
x+=1;
y+=1; /*upright square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
/*-------------------------------------------------------------*/
x-=2; /*upleft square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
/*-------------------------------------------------------------*/
y-=2; /*downleft square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
/*-------------------------------------------------------------*/
x+=2; /*downright square*/
if(x>=0&&x<X&&y>=0&&y<Y&&b[x][y]!='*')
{
b[x][y]+=1;
}
/*-------------------------------------------------------------*/
/*printf("Process%d:\n",num);
for(int i=0;i<X;i++)
for(int j=0;j<Y;j++)
{printf("%c",b[i][j]);if((j+1)%Y==0)printf("\n");}
num++;*/
return ;
}然后用一个循环合并上面的轰炸过程,轰炸区域为以(x-1,y-1)为起点的3*3的矩阵;
(如果你觉得测试数据,不都是雷块占少数的话,请看题解“Minesweeper”and“Sweepmine”)
#include <stdio.h>
void bombing( int x, int y );
int X, Y, M, N = 0;
int num = 1;
char b[100][100];
/*-------------------------------------------------------------*/
int main()
{
while ( scanf( "%d%d", &X, &Y ) && !(X == 0 && Y == 0) )
{
for ( int i = 0; i < X; i++ )
{
getchar(); /*clear data buffer cache*/
for ( int j = 0; j < Y; j++ )
{
scanf( "%c", &b[i][j] );
if ( b[i][j] == '.' )
b[i][j] = '0';
}
}
N++; /*the token of field;*/
for ( int i = 0; i < X; i++ )
for ( int j = 0; j < Y; j++ )
if ( b[i][j] == '*' )
bombing( i - 1, j - 1 );
printf( "Field #%d:\n", N );
for ( int i = 0; i < X; i++ )
for ( int j = 0; j < Y; j++ )
{
printf( "%c", b[i][j] ); if ( (j + 1) % Y == 0 )
printf( "\n" );
}
printf( "\n" );
}
}
/*-------------------------------------------------------------*/
void bombing( int x, int y )
{
for ( int i = x; i <= x + 2; i++ )
for ( int j = y; j <= y + 2; j++ )
if ( i >= 0 && i < X && j >= 0 && j < Y && b[i][j] != '*' )
b[i][j] += 1;
return;
}别忘按赞哦-.-
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复