天知道我是在怎样的精神状态下写出来的。

感觉是很新奇的随机化做法()


前 $4.5$ 秒,第一个排列开始找 next_permutation 并且 check。

前 $4.5\sim 9$ 秒,最后一个排列开始找 prev_permutation 并且 check。

前 $9\sim 9.995$ 秒,对于排列随机交换位置,然后如果答案与之前相同,有 $0.9$ 的概率交换。

最后 $0.005$ 秒用来输出。

随机种子写奇怪大质数就行。


https://www.luogu.com.cn/record/155391395

#include <bits/stdc++.h>
using namespace std;
#define getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++
char buf[1000000], *p1 = buf, *p2 = buf;
template <typename T>
void read(T &x)
{
    x = 0;
    int f = 1;
    char c = getchar();
    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-')
            f = -f;
    for (; c >= '0' && c <= '9'; c = getchar())
        x = x * 10 + c - '0';
    x *= f;
}
template <typename T, typename... Args>
void read(T &x, Args &...y)
{
    read(x);
    read(y...);
}
const int inf = 1e9;
mt19937 rnd(2010111901192009);
const int ED1 = 0.45 * CLOCKS_PER_SEC;
const int ED2 = 0.9 * CLOCKS_PER_SEC;
const int ED = 0.995 * CLOCKS_PER_SEC;
int R(int l, int r) { return rnd() % (r - l + 1) + l; }
int mp[30][30];
int n, m;
int p[30];
int ap[30];
int ans = inf;
int chosen[30];
void upd(bool f = 0)
{
    int tmp = 0;
    for (int i = 1; i <= n; i++)
        for (int j = i + 1; j <= n; j++)
            tmp += mp[p[i]][p[j]];
    for (int i = n + 1; i <= n << 1; i++)
        for (int j = i + 1; j <= n << 1; j++)
            tmp += mp[p[i]][p[j]];
    tmp = m - tmp;
    if (tmp > ans)
        return;
    if (tmp < ans)
    {
        ans = tmp;
        memcpy(ap, p, sizeof(ap));
        return;
    }
    if (!f)
    {
        if (R(1, 100) >= 90)
            memcpy(ap, p, sizeof(ap));
    }
}
void check()
{
    int l = R(1, n);
    int r = R(n + 1, n << 1);
    swap(p[l], p[r]);
    upd(1);
}
int main()
{
    read(n, m);
    for (int i = 1; i <= n; i++)
        p[i] = i;
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        read(u, v);
        mp[u][v] = mp[v][u] = 1;
    }
    n >>= 1;
    for (int i = 1; i <= n << 1; i++)
        chosen[i] = (i > n);
    do
    {
        int tot = 0;
        for (int i = 1; i <= n << 1; i++)
        {
            if (chosen[i])
                p[++tot] = i;
        }
        for (int i = 1; i <= n << 1; i++)
        {
            if (!chosen[i])
                p[++tot] = i;
        }
        upd();
        if (clock() > ED1)
            break;
    } while (next_permutation(chosen + 1, chosen + (n << 1) + 1));
    for (int i = 1; i <= n << 1; i++)
        chosen[i] = (i <= n);
    do
    {
        int tot = 0;
        for (int i = 1; i <= n << 1; i++)
        {
            if (chosen[i])
                p[++tot] = i;
        }
        for (int i = 1; i <= n << 1; i++)
        {
            if (!chosen[i])
                p[++tot] = i;
        }
        upd();
        if (clock() > ED2)
            break;
    } while (prev_permutation(chosen + 1, chosen + (n << 1) + 1));
    while (clock() < ED)
        check();
    for (int i = 1; i <= n; i++)
        cout << ap[i] << " ";
    cout << endl;
    return 0;
}
最后修改:2024 年 04 月 11 日
v我50吃疯狂星期四