| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3603 人关注过本帖
标题:啊哈!算法里的水管工游戏问题
只看楼主 加入收藏
水桃蜜蜜
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2016-5-9
结帖率:66.67%
收藏
已结贴  问题点数:26 回复次数:5 
啊哈!算法里的水管工游戏问题
为什么要取消标记????
递归函数中return;是直接跳出整体函数,还是跳出当前函数回到上一层dfs所在位置继续进行之后的代码啊????

#include <stdio.h>
#include <stdlib.h>
int a[51][51];
int book[51][51],n,m,flag=0;
struct note
{
    int x;
    int y;
}s[100];
int top=0;

void dfs(int x,int y,int front)
{
    int i;
    if(x==n && y==m+1)
    {
        flag=1;
        for(i=1;i<=top;i++)
        {
            printf("(%d,%d)",s[i].x,s[i].y);
        }
        return;
    }
    //判断是否越界
    if(x<1 || x>n || y<1 || y>m)
        return;
    //判断这个管道是否在路径中已经使用过
    if(book[x][y]==1)
    {
        return;
    }
    book[x][y]=1;//标记使用当前这个管道

    top++;
    s[top].x=x;
    s[top].y=y;
    //当前水管是直管的情况
    if(a[x][y]>=5 && a[x][y]<=6)
    {
        if(front==1)//进水口在左边的情况
        {
            dfs(x,y+1,1);
        }
        if(front==2)
        {
            dfs(x+1,y,2);
        }
        if(front==3)
        {
            dfs(x,y-1,3);
        }
        if(front==4)
        {
            dfs(x-1,y,4);
        }
    }
    if(a[x][y]>=1 && a[x][y]<=4)
    {
        if(front==1)//进水口在左边的情况
        {
            dfs(x+1,y,2);
            dfs(x-1,y,4);
        }
        if(front==2)
        {
            dfs(x,y+1,1);
            dfs(x,y-1,3);
        }
        if(front==3)
        {
            dfs(x-1,y,4);
            dfs(x+1,y,2);
        }
        if(front==4)
        {
            dfs(x,y+1,1);
            dfs(x,y-1,3);
        }
    }
/******************************************************取消标记*************/
    book[x][y]=0;/*******************************************************问题在这里*************/
    top--;/*******************************************************问题在这里*************/
    return;
}
int main()
{
    int i,j,num=0;
    scanf("%d %d",&n,&m);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    dfs(1,1,1);
    if(flag==0)
        printf("impossible\n");
    else
        printf("找到铺设方案\n");
    return 0;
}
/*
5 4
5 3 5 3
1 5 3 0
2 3 5 1
6 1 1 5
1 5 5 4
*/
搜索更多相关主题的帖子: include return 游戏 
2016-09-12 21:30
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:26 
哈哈,好巧,我也买了这本啊哈算法。所以看了一下书。

楼主问的book【x】[y]=0;//取消标记
之所以要在前面做标记,是为了保证从(x,y)出发去遍历的时候不会回到(x,y),导致无限循环
后面取消标记则是因为这一次我从(n,m)路径来到(x,y)再出发到其他结点的所有可能的路径都遍历完了,程序要往上递归了,那这些包括(x,y)和从(x,y)走出去的路径都需要抹掉还原,当做没走过的一样,然后程序来到(n,m)那一层,找除了(x,y)以外的其他结点继续遍历。

如果你不做这个取消标记的举动,那么对于整个图,你的所谓遍历算法只能使用每个结点1次!!!

图的遍历问题,最好得用动态的演示,应该会比较容易理解。我推荐《网易云课堂-数据结构与算法-陈越、何钦铭》的课程。
这个方法还是比较笨拙的,时间复杂度非常大。即使flag=1;//找到铺设方案了还是不能退出函数,浪费了大量的精力做多余的遍历。
继续往后面看,广度、深度优先就是一找到可行的铺设方案就会快速向上返回跳出函数


φ(゜▽゜*)♪
2016-09-12 22:49
水桃蜜蜜
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2016-5-9
收藏
得分:0 
回复 2楼 书生牛犊
有没有book【x】【y】=0;结果都一样为什么呢
2016-09-13 19:08
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
回复 3楼 水桃蜜蜜
结果一样是巧合,等着,我给你造一个案例。有两条路径又重合了部分点的。

φ(゜▽゜*)♪
2016-09-13 20:25
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:0 
图片附件: 游客没有浏览图片的权限,请 登录注册

像上面这种图,应该是有两条路径的。
测试代码如下。如果这时你把book[][]=0注释掉就只能输出第一条路径了。
图片附件: 游客没有浏览图片的权限,请 登录注册

为什么?因为第四行的那几个点在输出第一条路径的时候就已经用过了。不主动(3,3)(4,2)(4,3)(4,4)重置为0,就会被当做“弃子”错过

φ(゜▽゜*)♪
2016-09-13 20:45
水桃蜜蜜
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2016-5-9
收藏
得分:0 
回复 5楼 书生牛犊
谢谢!!!我结贴了
2016-09-13 21:01
快速回复:啊哈!算法里的水管工游戏问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.041785 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved