bzoj3033 太鼓达人——欧拉图搜索

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3033

考虑那 (1<<k) 个数,要形成答案,必然是相邻两个数间有 k-1 个重叠位置,也就是两个有 k-1 位前后对应相同的数之间可以连边转移;

发现这张图里每个点一定有两个入度、两个出度,也就是形成一张欧拉图;

所以暴搜时间有保证,暴搜即可;

对欧拉图还是太不熟悉了...暴搜也写不出来了...有种无力感...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=(1<<11)+5;//+5!!!
int k,m,ans[maxn],num,top,lst[maxn];
bool fl,vis[maxn];
void find(int y,int x)
{
    num=0;
    while(y!=x)ans[++num]=y,y=lst[y];
    ans[++num]=x;
}
void dfs(int x)
{
    vis[x]=1; top++;
    if(top==(1<<k)){find(x,0); fl=1; return;}
    for(int i=0;i<=1&&!fl;i++)
    {
        int y=((x&((1<<(k-1))-1))<<1|i);
        if(vis[y])continue;
        lst[y]=x; dfs(y);
    }
    vis[x]=0; top--;
}
int main()
{
    scanf("%d",&k);
//    m=(1<<k);//比下面慢 
//    printf("%d ",m);
    dfs(0);
    printf("%d ",num);
    for(int i=num;i;i--)printf("%d",(ans[i]>>(k-1)));
    return 0;
}

 

posted @ 2018-07-09 11:34  Zinn  阅读(122)  评论(0编辑  收藏  举报