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\n",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;
}

 

posted @ 2013-10-12 16:09  辰曦~文若  阅读(416)  评论(0编辑  收藏  举报