bzoj3033 太鼓达人 欧拉路/dfs

填坑……链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3033

题意:长度为定长的$0-1$串构成一个环形长串,这个长串中每一个元素开始的子串都不相同,输出长串的最长长度和最小字典序解。

看到了数据范围就想到了暴搜……但是考虑到我在刷图论的题(⊙﹏⊙)b,再加之仔细分析之后状态数会达到$2^2048$,难以承受。

但是这么放着也不是个事……于是我就想打个表找规律……结果暴搜搜$11$也瞬间出解……于是交了上去,然后,$A$了……

但是为什么暴搜会这么快呢……我们把每个子串对应的状态看做一个点,显然每个点都会由两个状态转化而来,每个点又会转化为两个新状态。入度和出度相等,这就变成了欧拉回路问题,然后时间复杂度就是$O(n)$的了……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<algorithm>
 5 using namespace std;
 6 string s,ans;
 7 int n,len,length;
 8 bool exist[1<<11];
 9 int tmp;
10 bool check(int add)
11 {
12     int x=0;
13     for(int i=s.size()-n+1;i<s.size();i++)x=(x<<1)|(s[i]-'0');
14     x=(x<<1)|add;
15     if(!exist[x])
16     {
17         tmp=x;
18         exist[x]=1;
19         return 1;
20     }return 0;
21 }
22 bool t;
23 void dfs(int num)
24 {
25     if(num>length)
26     {
27         cout<<length<<" ";
28         int cha=s.size()-length;
29         while(cha--)s.erase(s.end()-1);
30         cout<<s;t=1;exit(0);
31     }
32     if(s.size()>length)
33     {
34         if(check(0))
35         {
36             int l=tmp;
37             s+='0';
38             dfs(num+1);
39             s.erase(s.end()-1);
40             exist[l]=0;
41         }
42         return;
43     }
44     if(s.length()>=n+1&&check(0))
45     {
46         int l=tmp;
47         s+='0';
48         dfs(num+1);
49         s.erase(s.end()-1);
50         exist[l]=0;
51     }
52     if(s.length()<=length+1&&check(1))
53     {
54         int l=tmp;
55         s+='1';
56         dfs(num+1);
57         s.erase(s.end()-1);
58         exist[l]=0;
59     }
60 }
61 int main()
62 {
63     scanf("%d",&n);length=1<<n;
64     for(int i=1;i<=n;i++)s+='0';dfs(1);
65 }
bzoj3033
原文地址:https://www.cnblogs.com/Loser-of-Life/p/7354746.html