• 太鼓达人


    https://loj.ac/problem/10110

    题目描述

      有一个0、1环,有M个节点,并且满足从一个点出发顺时针K个节点所连接成的0、1串(共M个)都不相同,给出K,求最大的M和字典序最小的方案。

    思路

      我们考虑已知(K),那么二进制的排列总共有(2K)种,因此我们可以先证明,必定存在一种方案,使得(M)的排列满足这一条件。我们将(K-1)位的二进制看做点,把(K)位的二进制看做边,那么(a->b)的边即为在(a)后面加一个数字((0)(1)),这个二进制的后(K)位为(b),那么这样每个点必定有两条出边和两条入边,因此必定存在欧拉回路。由此归纳,对于任意(K),最大的(M)均为(2K)

      接下啦考虑如何求字典序最小的方案。显然对于欧拉回路,从路径上的任意一点出发都可以,所以前(K-1)位必定是(0),接下来进行(dfs),我们假设访问到当前节点为(x),那么记(x1)为在(x)后加一位(0)(x2)为在(x)后加一位(1)(x1)(x2)实际就是边的编号,每次(x)的后(K-1)位就是节点编号,所以我们可以直接(dfs)字典序小的边进行访问。注意要倒序输出,因为正序访问,答案是倒着存的。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1<<13;
    int ans[N],cnt,k,maxx;
    bool vis[N];
    void dfs(int x)
    {
        int x1=(x<<1)&maxx,x2=x1+1;
        if(!vis[x1])
        {
            vis[x1]=1;
            dfs(x1);
            ans[++cnt]=0;
        }
        if(!vis[x2])
        {
            vis[x2]=1;
            dfs(x2);
            ans[++cnt]=1;
        }
    }
    int main() 
    {
        int m;
        scanf("%d",&k);
        m=(1<<k);maxx=m-1;
        dfs(0);
        printf("%d ",m);
        for(int i=1;i<k;i++)printf("0");
        for(int i=m;i>=k;i--)
            printf("%d",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    15款经典图表软件推荐 创建最漂亮的图表
    CSS+JS打造的自适应宽度的滑动门和选项卡
    兼容多浏览器的加入收藏代码
    指针与引用深层次的区别
    反编译winform资源文件
    程序创业必过三关
    自动ping博客服务程序
    C#批量加水印程序
    C#应用程序随机启动
    失败降临是命中注定
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11752878.html
Copyright © 2020-2023  润新知