返回首页
专题
网络编程
ASPjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 .NETjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 PHPjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 JSPjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 C#jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Javajrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Delphijrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 VBjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 C/C++jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Android开发 IOS开发 Windows Phone开发 Pythonjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Rubyjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 移动开发 其他编程jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播
网页制作
HTMLjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 CSSjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Dreamweaverjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 FrontPagesjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Javascriptjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 web前端
数据库
SqlServer MySql Oracle Access DB2 SQLite 其他数据库
图形设计
photoshopjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Fireworksjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 CorelDrawjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Illustratorjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 AutoCadjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 FLASHjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播
操作系统
Windows xpjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Windows 7jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Windows 8jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Windows 2003jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Windows Server 2008jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Linuxjrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 Windows 10
网站运营
建站经验 SEO优化 站长心得 网赚技巧 网站推广 站长故事
手机学院
手机速递 安卓jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 iphonejrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 手机评测 手机技巧 手机知识 手机应用 手机游戏 手机导购
网店宝典
开店指导 开店经验 网店装修 网店推广 网店seo 网购技巧
软件jrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播
办公软件 系统工具 媒体工具 压缩工具 图文处理 文件管理
范文之家
自我介绍 自我鉴定 写作模板 合同范本 工作总结 贺词祝福语 演讲致辞 思想汇报 入党申请书 实习报告 心得体会 工作计划 简历模板 工作报告 导游词 评语寄语 口号大全 策划书范文
信息工程
软件工程 企业开发 系统运维 软件测试
移民之家
移民动态 移民政策 移民百科 移民生活 技术移民 投资移民
知识大全
母婴 数码 摄影 装修 美文 常识 时尚 婚嫁 美食 养生 旅游 兴趣 职场 教育 文学 健康
问答大全
电脑网络 手机数码 QQ专区 生活 游戏 体育运动 娱乐明星 休闲爱好 文化艺术 社会民生 教育科学 健康医疗 商业理财 情感家庭 地区问题 其他
编程问答
IOS Android .NET Java C/C++ Delphi VC/MFC 其他语言 PHP MSSQL MYSQL Oracle 其他数据库 Web开发 Windows Linux 硬件/嵌入开发 网络通信 移动开发 云计算 企业IT 游戏开发
笑话大全
幽默笑话 爱情笑话 成人笑话 校园笑话 爆笑笑话 综合笑话 古代笑话 现代笑话 国外笑话

光圈优先快门优先 玩转深度优先搜索算法

来源:互联网  时间:2016/8/1 9:24:38

小时候玩游戏,有个BOMB人的游戏,把BOMB放在一个空地上,将怪兽炸死,如图:
 玩转深度优先搜索算法

BOMB的威力只要不碰到墙壁,可以无限延长。那么我们应该把BOMB放哪里可以炸死最多的怪兽呢?

这个问题貌似很简单,一个一个地方试下不就知道了吗?是啊,那我们用代码来试下。

将图象转成字符,用#表示墙,用G表示怪兽,用.表示空地,最后得到的字符为:

#############

#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#

#############

那我只要把所有的空地试下就知道哪里放BOMB最好了。

int main()
{
    char a[20][20];
    int i, j, sum , map, p, q = 0;
    int n, m, x, y; //m表示多少行字符,n表示多少列字符
    scanf("%d %d", &n, &m);

    for(i = 0; i <= n - 1; i++)
    {
        scanf("%s", a[i]);
    }

    for (i = 0; i <= n - 1; i++)
    {
        for (j = 0; j <= m - 1; j++)
        {
            //判断当前所在位置是不是平地,是平地才可以放BOMB
            if(a[i][j] != '.')
            {
                continue;
            }

            //当前可以炸0个怪兽
            sum = 0;

            x = i;
            y = j;

            //向上扩展计算消灭的怪兽数
            while(a[x][y] != '#')
            {

                if(a[x][y] == 'G')sum++;
                x--;
            }

            x = i;
            y = j;

            //向下扩展计算消灭的怪兽数
            while(a[x][y] != '#')
            {

                if(a[x][y] == 'G')sum++;
                x++;
            }

            x = i;
            y = j;

            //向左扩展计算消灭的怪兽数
            while(a[x][y] != '#')
            {

                if(a[x][y] == 'G')sum++;
                y--;
            }

            x = i;
            y = j;

            //向右扩展计算消灭的怪兽数
            while(a[x][y] != '#')
            {

                if(a[x][y] == 'G')sum++;
                y++;
            }

            //如果消灭的怪兽大于map,则更新map,并记住所在的坐标
            if(sum > map)
            {
                map = sum;
                p = i;
                q = j;
            }
        }
    }

    printf("将BOMB放在(%d,%d)处,可以消灭最多%d怪兽只\n", p, q, map);
    getchar();
    getchar();
    return 0;
}

 打印结果为:将BOMB放在(1,11)处,可以消灭最多11怪兽只。这种算法为枚举,

好像有点不对劲啊,小人根本到不了(1,11),所以那里根本不放了BOMB。所以说我们不能将所有的空地都计算进去,需要将到不了的空地排除。这里该深度优先算法出场了(当然还有其它算法可以解决)。

走过迷宫的都知道,我们会沿一条走到头,死路时就回头,回到上一个岔路口,已经确定了一条死路,我们就走另一条路,又是死路,我们就再回到岔路口,两条都是死路了,就回到上上个岔路口,依此循环。

这个问题就像小人在走迷宫,直到所有的空地都被小人走过为此。我们用递归来实现这个逻辑:

char a[20][21];
int book[20][20];//标记某个点是否被走过
int max, mx, my, n, m;

//计算当前空地可以炸死的怪兽
int getSum(int i, int j)
{
    int sum, x, y;
    //当前可以炸0个怪兽
    sum = 0;

    x = i;
    y = j;

    //向上扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        x--;
    }

    x = i;
    y = j;

    //向下扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        x++;
    }

    x = i;
    y = j;

    //向左扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        y--;
    }

    x = i;
    y = j;

    //向右扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        y++;
    }

    return sum;
}

void dfs(int x, int y)
{
    //定义上下左右走动时x,y轴的变化
    int next[4][2] = {{0, 1}, {0, -1}, {1, 0}, { -1, 0}};

    int k, sum, tx, ty;

    sum = getSum(x, y);

    if(sum > max)
    {
        max = sum;
        mx = x;
        my = y;
    }

    for(k = 0; k <= 3; k++)
    {
        tx = x + next[k][0];
        ty = y + next[k][1];

        if(tx < 0 || tx > n - 1 || ty < 0 || ty > n - 1)continue;

        if(a[tx][ty] == '.' && book[tx][ty] == 0)
        {
            book[tx][ty] = 1;//标记走过这个空地了
            dfs(tx, ty);//走向下一个空地
        }
    }
    return ;
}

int main()
{
    int i, startx, starty;

    scanf("%d %d %d %d", &n, &m, &startx, &starty);

    for(i = 0; i <= n - 1; i++)
    {
        scanf("%s", a[i]);
    }

    book[startx][starty] = 1;
    mx = startx;
    my = starty;
    max = getSum(startx, starty);

    dfs(startx, starty);
    printf("将BOMB放置在(%d,%d),最多可以消灭%d个怪兽\n", mx, my, max );
    return 0;
}

 得到结果:将BOMB放置在(7,11),最多可以消灭10个怪兽。

我再用“栈”来实现:

char a[20][21];

//栈的节点
struct  note
{
    int x;
    int y;
};

//获取当前空地能消灭的怪兽数
int getSum(int i, int j)
{
    int sum, x, y;
    //当前可以炸0个怪兽
    sum = 0;

    x = i;
    y = j;

    //向上扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        x--;
    }

    x = i;
    y = j;

    //向下扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        x++;
    }

    x = i;
    y = j;

    //向左扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        y--;
    }

    x = i;
    y = j;

    //向右扩展计算消灭的怪兽数
    while(a[x][y] != '#')
    {

        if(a[x][y] == 'G')sum++;
        y++;
    }

    return sum;
}

int main()
{
    //初始化一个栈
    struct note que[401];
    int book[20][20];
    int n,m,mx,my,max,top=0, i, startx, starty;

    scanf("%d %d %d %d", &n, &m, &startx, &starty);

    for(i = 0; i <= n - 1; i++)
    {
        scanf("%s", a[i]);
    }

    book[startx][starty] = 1;
    mx = startx;
    my = starty;
    //当起始点加入到栈中
    top++;
    que[top].x = startx;
    que[top].y = starty;
    max = getSum(startx, starty);

    int next[4][2] = {{0, 1}, {0, -1}, {1, 0}, { -1, 0}};

    int k, sum, tx, ty;

    //直到栈空了
    while(top != 0)
    {
        sum = getSum(que[top].x, que[top].y);

        if(sum > max)
        {
            max = sum;
            mx = que[top].x;
            my = que[top].y;
        }

        for(k = 0; k <= 3; k++)
        {
            tx = que[top].x + next[k][0];
            ty = que[top].y + next[k][1];

            if(tx < 0 || tx > n - 1 || ty < 0 || ty > n - 1)continue;

            if(a[tx][ty] == '.' && book[tx][ty] == 0)
            {
                book[tx][ty] = 1;
                top++;
                que[top].x = tx;
                que[top].y = ty;
                break;
            }
            //这句很关键,一个空地上下左右都试走过后,将此空地移除栈
            if(k == 3)top--;
        }
    }
    printf("将BOMB放置在(%d,%d),最多可以消灭%d个怪兽\n", mx, my, max );
    return 0;
}

 得到的结果是一样的。

这套算法应用十分广泛,可以解决很多问题。作为一名码农还是非常有必要学习一下的。


上一篇从尾到头打印链表
下一篇java 定时器 Timer
明星图片
相关文章
《光圈优先快门优先 玩转深度优先搜索算法》由码蚁之家搜集整理于网络,
联系邮箱:mxgf168#qq.com(#改为@)