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

来源:互联网 发布:sql语言查询 编辑:程序博客网 时间:2024/05/18 02:06
解法:先将每个点之间的可达性用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()里面的参数只用记录当前总数即可。也可采取在主程序中枚举起点的办法。

1 0