太鼓达人【欧拉回路】【DFS】

题目大意:

给出一个01串,从不同的位置出发沿顺时针方向找可以得到M个长度为K的01串。且这M个01串是互不相同的。给出K的值,请你求出M的值,并给出字典序最小的方案。
Input

3

Output

00010111

思路:

n11,打标了解一下233
但是打到n=6,跑了一个半小时都没跑出来。。。(时间复杂度:O4n
正解是欧拉回路。
但是我打的和其他大佬打的。。。
这里写图片描述
差距怎么这么大啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!!
前面三页都是1ms的。。。


我跑的十分的慢的原因是我先跑了一个O(2n)的全拍列,再O(m2n)求出十进制的数字,最后O(2n)求出答案。但是他们直接O(2n),遍跑遍建边就过了。。。
这道题求出01串的全排列后,将他们的十进制打出来,再跑一遍,找出欧拉回路,输出答案就可以了。


#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int n,m,a[3001][3001],num[3001][15],t[3001],mi[15],ans[3001],sum,o;
string head[3001],tail[3001];
bool ok,p[3001];

void dfs1(int x)  //全排列
{
    if (x>n)  //找到一种全排列
    {
        for (int i=1;i<=n;i++)
        {
            num[m][i]=t[i];
            if (i>1) tail[m]+=(char)t[i]+48;
            if (i<n) head[m]+=(char)t[i]+48;
        }
        m++; 
        return;
    }
    for (int i=0;i<=1;i++)
    {
        t[x]=i;
        dfs1(x+1);
        t[x]=0;
    }
    return;
}

int conversion(int x)  //转化为十进制
{
    sum=0;
    for (int i=1;i<=n;i++)
     sum+=mi[i]*num[x][i];
    return sum;
}

void dfs2(int x,int k)  //求欧拉回路
{
    if (k>m&&x==o)  //找到欧拉回路
    {
        ok=true;
        return;
    }
    for (int i=0;i<m;i++)
     if (a[x][i]&&!p[i])  //可以通往这条边
     {
        p[i]=true;
        dfs2(i,k+1);
        if (ok)  //找到欧拉回路
        {
            ans[k]=i&1;  //二进制最后一位
            return;
        }
        p[i]=false;
     }
}

int main()
{
    scanf("%d",&n);
    dfs1(1);  //求全排列
    printf("%d ",m);
    mi[n]=1;
    for (int i=n-1;i>=1;i--)
     mi[i]=mi[i+1]*2;
    for (int i=0;i<m;i++)
     for (int j=0;j<m;j++)
      if (i!=j&&head[j]==tail[i])
      {
         a[conversion(i)][conversion(j)]=1;  //转十进制
      }
    o=m-1;
    dfs2(o,1);
    for (int i=1;i<=m;i++) printf("%d",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313029.html