博客题解:https://www.cnblogs.com/Tyouchie/p/10385615.html
题目描述
太鼓达人的鼓坏了,现在vani来修鼓。
鼓的主要元件是 M 个围成一圈的传感器。
每个传感器都有开和关两种工作状态,分别用 1 和 0 表示。
显然,从不同的位置出发沿顺时针方向连续检查 K 个传感器可以得到 M 个长度为 K 的 01 串。
Vani 知道这 M 个 01 串应该是互不相同的。
而且鼓的设计很精密,M 会取到可能的最大值。
现在 Vani 已经了解到了 K 的值,他希望你求出 M 的值,并给出字典序最小的传感器排布方案。
输入格式
一个整数K。
输出格式
一个整数和一个二进制串,由一个空格分隔,分别表示可能的最大的 M 以及字典序最小的排布方案。
字符 0 表示关,1 表示开,你输出的串的第一个字和最后一个字是相邻的。
数据范围
2≤K≤11
输入样例:
3
输出样例:
8 00010111
算法
题意:给出k,求一个最长的M位01串,使其从每一个位置向后走k个得到的M个k位01串互不相同(最后一个和第一个相邻,即是一个环)。输出字典序最小的答案。 2 ≤ k ≤ 11。
反正就是 结论+爆搜;
第二问我们将每个k二进制数看成一个点,在它后面加上0/1就能得 到两个新数,我们从这个数向两个新数连边,于是这就变成了求一个欧拉回路的问题。
显然此题是存在欧拉回路的第一问答案为2的k次方 ,第二问暴力求欧拉回路即可。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+50;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int n,t,ans[maxn];
bool used[maxn];
inline bool eular(int x,int k)//x是当前子串的十进制表示,k是当前查询次
{
if(used[x]) return 0;
used[x]=1,ans[k]=x&1;//统计答案,&的规则是:有零则零,否则为一,返回末位数字
if(k==t) return 1;//查询结束
if(eular((x<<1)&(t-1),k+1)) return 1;
if(eular((x<<1|1)&(t-1),k+1)) return 1;//将每个二进制数看成一个点,将他前面的数删去,并在它后面加上0/1就能得到两个新数
used[x]=0;//回溯,以免影响之后的dfs
return 0;
}
int main()
{
read(n);
t=1<<n;
printf("%d ",t);
eular(t-2,1);//从每位走n位子串,可得到的完整子串数量为2^n-2
for(int i=1;i<=t;++i)
printf("%d",ans[i]);
return 0;
}