zoukankan      html  css  js  c++  java
  • UVA 291 The House Of Santa Claus (DFS求一笔画)

    题意:从左下方1开始,一笔画出圣诞老人的屋子(不过话说,圣诞老人的屋子是这样的吗?这算是个屋子么),输出所有可以的路径。

    思路:贴代码。

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    int head[20],tot=0,val;//val:用整型值存储结果,因为最后输出是要按大小排序
    int vis[20];//用来标记边是否已经走过,若已经走过,则接下来就不能走该条边
    int len;//满足一笔画的答案个数
    int ans[510];//存储答案
    struct Edge{
        int to,next;
    }edge[20];
    
    //建立双向边
    void add(int u,int v){
        edge[tot].next=head[u];
        edge[tot].to=v;
        head[u]=tot++;
    
        edge[tot].next=head[v];
        edge[tot].to=u;
        head[v]=tot++;
    }
    
    void init(){
        memset(head,-1,sizeof(head)); //一开始忘记初始化head了。。。
        add(1,5);add(1,3);add(1,2);
        add(2,5);add(2,3);
        add(3,5);add(3,4);
        add(4,5);
    }
    //u:当前走到的点;idx表示已经走过了idx条边,总计需要走完8条边
    void dfs(int u,int idx){
        if(idx==8){
            val=val*10+u;
            ans[len++]=val;
            val/=10;
            return;
        }
        for(int k=head[u];k!=-1;k=edge[k].next){
            if(vis[k])
                continue;   //若第k条边已经走过,则继续尝试其它边
            int v=edge[k].to;
            /*
            因为是双向边,相同端点的会有两条,走过其中一条后,另一条也要标记走过,因为每条边只能走一次,一开始就是这里给忽略了。
            若k为偶数,第k边端点为u、v,则第k+1边端点也为u、v,要同时标记走过。
            若k为奇数,第k边端点为u、v,则第k-1边端点也为u、v,要同时标记走过。
            */
            if(k%2==0){
                vis[k]=1;
                vis[k+1]=1;
            }
            else{
                vis[k]=1;
                vis[k-1]=1;
            }
            val=val*10+u;
            dfs(v,idx+1);
            //最后要恢复原来的值,不能影响之后的遍历
            val=val/10;
            if(k%2==0){
                vis[k]=0;
                vis[k+1]=0;
            }
            else{
                vis[k]=0;
                vis[k-1]=0;
            }
        }
    }
    
    int main()
    {
        init();
        len=0;
        memset(vis,0,sizeof(vis));
        val=0;
        //从左下角1开始dfs
        dfs(1,0);
    
        sort(ans,ans+len);
        for(int i=0;i<len;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }

    贴个书上的参考程序:

    #include <iostream>
    #include <string>
    #include <cstring>
    //因为数据量很小,用邻接矩阵,15ms,而且输出顺序即按照大小顺序排。
    using namespace std;
    int edge[6][6];
    void makeEdge(){
        memset(edge,0,sizeof(edge));
        for(int i=1;i<=5;i++){
            for(int j=1;j<=5;j++){
                if(i!=j)
                    edge[i][j]=1;
            }
        }
        edge[4][1]=edge[1][4]=0;
        edge[4][2]=edge[2][4]=0;
    }
    //目前已画了k条边,准备将x扩展为s的第k+1条边的端点
    void dfs(int x,int k,string s){
        s+=char(x+'0');
        if(k==8){
            cout<<s<<endl;
            return;
        }
        for(int y=1;y<=5;y++){
            if(edge[x][y]){
                edge[x][y]=edge[y][x]=0;
                dfs(y,k+1,s);
                edge[x][y]=edge[y][x]=1;
            }
        }
    }
    int main()
    {
        makeEdge();
        dfs(1,0,"");
        return 0;
    }
  • 相关阅读:
    织梦当前位置去除最后字符
    一霎清明雨,实现考勤管理。
    浅谈:C#中的非泛型集合
    简述结构和类的区别
    项目经理评分系统
    那些年我们一起~做过的魔兽系统
    浅谈:什么是.NET
    MyKTV系统项目的感想
    开发“航班查询及预定”系统
    java面试的一些问题
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3365448.html
Copyright © 2011-2022 走看看