搜索之“炸弹人”

先来说说题目意思吧,如图,帮助小人找到一个放炸弹的坐标,使之一颗炸弹炸死最多的敌人。
炸弹人题目示意图
我们用字符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;
}

好了,代码就是这样的,测试数据和上面的深搜一样,好好比较下,好好领悟!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值