先来说说题目意思吧,如图,帮助小人找到一个放炸弹的坐标,使之一颗炸弹炸死最多的敌人。
我们用字符G表示敌人,#表示墙, . 表示可以走的路,特别说明下,那种一推就倒的墙,就把它看做路吧。
下面就来搜索来一下吧:
/*
来让我们小小的说明下深搜的要点:
1、解决当前任务是什么。
2、什么时候我该休息。
3、当前任务做完了,下一步怎么做。
怎么样很好理解的吧
*/
#include<stdio.h>
#include<string.h>
char map[20][20];//存储图
int mark[20][20];//标志图中的位置是否到达过
int m,n;//m行n列的图
int ex,ey;//需要的出的坐标
int max;
//位于(x,y)坐标是应该怎么处理,这里的x,y表示的是第x行,第y列
void DFS(int x,int y){
/*
*这个时候该结束了,可以休息了
*
*当前位置可不能是图的外部 ,当然走过了耶不用走了
*/
if(x>=m || x<1 || y>=n || y<1 || mark[x][y] || map[x][y]=='G' || map[x][y]=='#'){
return ;
}
/*
*当前我的任务是这个,统计我能消灭的敌人
*
*从这里向下可以写为一个函数
*/
int sum=0;
int tx,ty;
tx = x,ty=y;
while(map[tx][ty]!='#'){
//统计当前位置以上敌人数量
if(map[tx][ty]=='G'){
sum++;
}
tx++;
}
tx=x;ty=y;
while(map[tx][ty]!='#'){
//统计当前位置以下的敌人
if(map[tx][ty]=='G'){
sum++;
}
tx--;
}
tx=x;ty=y;
while(map[tx][ty]!='#'){
//统计当前位置左边的敌人
if(map[tx][ty]=='G'){
sum++;
}
ty--;
}
tx=x;ty=y;
while(map[tx][ty]!='#'){
//统计当前位置左边的敌人
if(map[tx][ty]=='G'){
sum++;
}
ty++;
}
/*从这里向上可以写为一个函数*/
//更新最大值
if(sum>max){
max = sum;
ex = x;
ey = y;
}
mark[x][y]=1;//这个点走过了,就不要了
/*
*当前任务做完了,我可以接下一个任务了
*下一步可以上下左右的选择一下
*/
DFS(x+1,y);
DFS(x-1,y);
DFS(x,y-1);
DFS(x,y+1);
return ;
}
int main(){
memset(mark,0,sizeof(mark));
max=0;
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
scanf("%s",map[i]);
}
DFS(2,3);//假设从2,3出发
printf("最佳坐标:(%d,%d),可以干掉敌人%d个!",ex,ey,max);
return 0;
}
/*
***测试数据:
13 13
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#.......#..G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.#.#
##G...G.....#
#G#.#G###.#G#
#...G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############
*/
上面的看懂了没呢,倒杯茶,静心想一想。
下面补充一下广搜的做法,以便比较学习:
在广搜中,从一个点(s表示)出发,我们优先遍历他能到达的所有的下一个点(n1,n2…..),然后将s点抛弃,在遍历n1可以到达的所有点,抛弃n1,遍历n2可以到达的所有点,抛弃n2……一直这样下去,知道所有点都被遍历。有没有发现,上面的特征很符合队列呢,先进去的先被抛弃。。。下面看看代码:
//炸弹人之广搜
#include<stdio.h>
#include<string.h>
struct node{
int x;//当前横坐标
int y;//当前纵坐标
};
struct node que[401];//这里用数组模拟队列的操作
int head,tail;//队首和队尾指针
char map[20][20];//存储地图
int mark[20][20];//标志
//这个是下一步的坐标辅助数组,想一想为啥这样填数据
int next[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int sx,sy,ex,ey,m,n;//开始,结束的横纵坐标,图的大小
int max;//最多可以干掉的敌人数
int get(int x,int y){
int sum=0;
int tx,ty;
tx = x,ty=y;
while(map[tx][ty]!='#'){
//统计当前位置以上敌人数量
if(map[tx][ty]=='G'){
sum++;
}
tx++;
}
tx=x;ty=y;
while(map[tx][ty]!='#'){
//统计当前位置以下的敌人
if(map[tx][ty]=='G'){
sum++;
}
tx--;
}
tx=x;ty=y;
while(map[tx][ty]!='#'){
//统计当前位置左边的敌人
if(map[tx][ty]=='G'){
sum++;
}
ty--;
}
tx=x;ty=y;
while(map[tx][ty]!='#'){
//统计当前位置左边的敌人
if(map[tx][ty]=='G'){
sum++;
}
ty++;
}
return sum;
}
void BFS(){
//队列初始化
head = tail = 0;
//将开始点入队
que[tail].x = sx;
que[tail].y = sy;
//向后移动队尾
tail++;
mark[sx][sy]=1;//走过了就不要了
int sum;
max= get(sx,sy);
int nx,ny;
while(head<tail){
//枚举下一步
for(int i=0;i<4;i++){
nx = que[head].x + next[i][0];
ny = que[head].y + next[i][1];
//这些情况是不能走的,直接下一步
if(nx>=m || nx<1 || ny>=n || ny<1 || mark[nx][ny] || map[nx][ny]=='G' || map[nx][ny]=='#'){
continue;
}
//可以走的当然要加入队列
mark[nx][ny]=1;
que[tail].x = nx;
que[tail].y = ny;
tail++;
//更新最大值
sum = get(nx,ny);
if(sum>max){
max = sum;
ex = nx;
ey = ny;
}
}
head++;//不要忘了,要换老大了,当然要向后移动
}
}
int main(){
memset(mark,0,sizeof(mark));
max=0;
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
scanf("%s",map[i]);
}
printf("输入开始的坐标,不能在墙里,也不能和敌人共舞吧!") ;
scanf("%d%d",&sx,&sy);
BFS();
printf("最佳坐标:(%d,%d),可以干掉敌人%d个!",ex,ey,max);
return 0;
}
好了,代码就是这样的,测试数据和上面的深搜一样,好好比较下,好好领悟!