zoukankan      html  css  js  c++  java
  • zoj 3861 Valid Pattern Lock(以及自己对dfs的一些理解)

    解法:先将每个点之间的可达性用c[][]记录,为0的话代表可以直接走到。但是如果要进行像3 1 2 这样的走法的话必须要先经过他们中间的点2,否则是不能走的。

    用c[i][j]记录i和j之间必须要经过的点。然后进行dfs搜索即可。

    经过这道题,自己对dfs的递归过程又有了更加深刻的了解。一开始的时候对dfs里面的参数有些疑虑,-->像这样dfs(s[0],0),但是这样的话,每次都要先判断c[x][s[i]]

    这样是错误的。dfs(0,0)的话,因为0与1~9都是可以直接到达的(0是自己添加的),所以可以得出所有情况。还有就是想要记录路径的时候要注意,看注释。

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int T,n,ans;
    int s[20],path[20];
    int c[20][20];
    int vis[20];
    int v[150000][12];
    
    void dfs(int x,int sum)
    {
        if(sum>=n)
        {
            for(int i=0;i<n;i++)//记录路径 
            v[ans][i]=path[i];
            
            ans++;
            return ;
        }
        for(int i=0;i<n;i++)
        {
             if(!vis[s[i]])
            {
                    if(c[x][s[i]]==0)
                    {
                      path[sum]=s[i];
                     // v[ans][sum]=s[i]; ans前面的都为空,并未赋值,所以错误 
                      vis[s[i]]=1;
                      dfs(s[i],sum+1);
                      vis[s[i]]=0;
                    }
                    else if(c[x][s[i]]&&vis[c[x][s[i]]]==1)
                    {
                         path[sum]=s[i];
                      //v[ans][sum]=s[i];
                      vis[s[i]]=1;
                      dfs(s[i],sum+1);
                      vis[s[i]]=0;
                    }
            }
    
        }
    
    }
    
    int main()
    {
        memset(c,0,sizeof(c));  
        c[1][3]=2,c[3][1]=2;  
        c[1][7]=4,c[7][1]=4;  
        c[1][9]=5,c[9][1]=5;  
        c[2][8]=5,c[8][2]=5;  
        c[3][9]=6,c[9][3]=6;  
        c[3][7]=5,c[7][3]=5;  
        c[4][6]=5,c[6][4]=5;  
        c[7][9]=8,c[9][7]=8; 
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            memset(vis,0,sizeof(vis));
            ans=0;
            for(int i=0;i<n;i++)
            scanf("%d",&s[i]);
            sort(s,s+n);
            dfs(0,0);//0与所有的点都是连接可以到达的 
            printf("%d
    ",ans);
            
            for(int i=0;i<ans;i++)
            {
                printf("%d",v[i][0]);
                for(int j=1;j<n;j++)
                printf(" %d",v[i][j]);
                printf("
    ");
            }    
            
        }
        return 0;
    }

    另附dfs生成全排列的算法,是这道题的原型。

    #include<iostream>
    #include<cstring>
    using namespace std;
    int vis[10],n;
    int ans[10];
    
    void dfs(int sum)
    {
        if(sum>n)
        {
            int first=0;
            for(int i=1;i<=n;i++)
            {
                if(first++)
                cout<<" ";
                cout<<ans[i];
            }
            cout<<endl;
            
        }
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                vis[i]=1;
                ans[sum]=i;
                dfs(sum+1);
                vis[i]=0;
            }
        }
    }
    
    int main()
    {
        cin>>n;
        memset(vis,0,sizeof(vis));
        dfs(1);
    }

    dfs()里面的参数只用记录当前总数即可。也可采取在主程序中枚举起点的办法。

  • 相关阅读:
    Oracle中查看建立索引和使用索引的注意点
    一个父亲的教育札记——leo鉴书58
    puma 配置,启动脚本
    HDU 6003 Problem Buyer
    c# 类间关系
    前台线程和后台线程总结
    多线程学习进程
    进程类的使用
    c#异步编程
    【程序17】
  • 原文地址:https://www.cnblogs.com/Tach-ac/p/4430753.html
Copyright © 2011-2022 走看看