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

    }
    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()里面的参数只用记录当前总数即可。也可采取在主程序中枚举起点的办法。

时间: 2024-10-14 12:22:27

zoj 3861 Valid Pattern Lock(以及自己对dfs的一些理解)的相关文章

DFS+模拟 ZOJ 3861 Valid Pattern Lock

题目传送门 1 /* 2 题意:手机划屏解锁,一笔连通所有数字,输出所有可能的路径: 3 DFS:全排列 + ok () 判断函数,去除一些不可能连通的点:) 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <cstring> 9 #include <string> 10 #include <map> 11 #includ

ZOJ 3861 Valid Pattern Lock DFS

每个点有16种方向,向某个方向走一步或者两步,dfs把找到的数都存下来就可以了..... Valid Pattern Lock Time Limit: 2 Seconds      Memory Limit: 65536 KB Pattern lock security is generally used in Android handsets instead of a password. The pattern lock can be set by joining points on a 3

ZOJ - 3861 Valid Pattern Lock(dfs或其他,两种解法)

Valid Pattern Lock Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Submit Status Description Pattern lock security is generally used in Android handsets instead of a password. The pattern lock can be set by joining points on

zoj 3861 Valid Pattern Lock(全排列 模拟)

#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<stdlib.h> #include<queue> #include<stack> #include<vector> #include<algorithm> #define LL long long using namespace std; i

浙江大学2015年校赛B题 ZOJ 3861 Valid Pattern Lock

这道题目是队友写的,貌似是用暴力枚举出来. 题意:给出一组数,要求这组数在解锁的界面可能的滑动序列. 思路:按照是否能够直接到达建图,如1可以直接到2,但是1不能直接到3,因为中间必须经过一个2. 要注意的假如2已结访问过,那么1就可以直接到2. 建图DFS,图要更新. Source Code: #include <stdio.h> #include <string.h> int node[10], ans[10], n, vis[10], k, fun[1000000][10];

ZOJ 3861 Valid Pattern Lock

题意:画图案所的问题,给出一个3 × 3拨号盘中的几个数字作为活跃点,问由活跃点能组合多少种解锁方式,并输出它们.一个合法的解锁方式包含以下几点: 一个方案中由一些点构成,每个点在按顺序触摸的时候都是第一次被触摸到,称这些点为活跃点. 如果在连接A,B两点的时候经过了另外的点,那么这个点必须出现在序列中,并且在A和B之前出现. 一个点被合法的线段多次通过是可以的,只要这个点在之前合法出现过. 解法:枚举排列,挨个判断是否合法,因为之前读错过题……所以写的比较啰嗦……正常应该不是很难写……就不介绍

[水题+dfs] zoj 3861 Valid Pattern Lock

题意: 给n个不同的整数(3<=n<=9),问你能绘制出多少种解锁的方案. 输出方案数,以及按字典序输出每种方案. 思路: 一个很水的dfs全排列,加上特判就好了. 特判就是1->9的话就必定经过5等. 这里要注意的是. 中间所经过的数字是必须存在的. 比如要想1->9就必须有5. 5要么被用过,要么就经过5 例子就是 1 3 5 9这四个数. 实际的方案是只有2种 3 5 1 9 和 3 5 9 1 然后就是输入完排下序,保证字典序. 最后就是弱太弱了,写了2个dfs一个算个数,

ZOJ Problem Set - 3861 Valid Pattern Lock(dfs)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3861 这道题当时没做出来,后来经过队友提醒才做出来. 3*3的九宫格,给你其中n个点按下面要求连起来: 1. 给你的n个点都要激活(至少经过一次) 2. 如果点A,B相连后要经过另一个点C,则C在序列中的位置必须在A,B之前 如 1 7 4是不合法的 3.线段相交是没关系的,如 7 6 9 4 我是直接生成n个数的全排列,然后在所有排列里面去掉不合法的. 1 #inclu

Valid Pattern Lock

Time Limit: 2 Seconds      Memory Limit: 65536 KB Pattern lock security is generally used in Android handsets instead of a password. The pattern lock can be set by joining points on a 3 × 3 matrix in a chosen order. The points of the matrix are regis