AcWing 400 贪心 + 欧拉回路

题意

传送门 AcWing 400 太鼓达人

题解

长度为 K K K 01 01 01 串共有 2 K 2^K 2K 种,需尽可能多地通过环上的顺时针移动,遍历不同的 01 01 01 串,并返回初始串。将 K K K 长的 01 01 01 串看做边,权值为 01 01 01 串的最后一位数字,将出边代表的 01 01 01 串的 K − 1 K-1 K1 长前缀看做点。每个点各有 2 2 2 条出边与入边,则存在有向图的欧拉回路。以点 0 0 0 为起点求解欧拉回路,为保证字典序最小,贪心地从权值较小的边开始递归。总时间复杂度 O ( 2 K ) O(2^K) O(2K)

#include <bits/stdc++.h>
using namespace std;
const int maxk = 12, maxn = 1 << maxk, maxm = maxn << 1;
int K, nr, res[maxn];
int tot, head[maxn], to[maxm], nxt[maxm], cost[maxm];
bool vs[maxn];

inline void add(int x, int y, int z)
{
    
    
    to[++tot] = y, cost[tot] = z, nxt[tot] = head[x], head[x] = tot;
}

void euler(int x)
{
    
    
    for (int &i = head[x], y, z; i;)
    {
    
    
        y = to[i], z = cost[i], i = nxt[i];
        euler(y);
        res[++nr] = z;
    }
}

int main()
{
    
    
    scanf("%d", &K);
    int t = 1 << (K - 1);
    for (int i = 0; i < t; ++i)
    {
    
    
        int j = (i << 1) & (t - 1);
        add(i, j | 1, 1), add(i, j, 0);
    }
    euler(0);
    printf("%d ", 1 << K);
    for (int i = 1; i < K; ++i)
        putchar('0');
    while (nr >= K)
        putchar(res[nr--] + '0');
    putchar('\n');
    return 0;
}

猜你喜欢

转载自blog.csdn.net/neweryyy/article/details/115012430