CF1310D Tourism
解题思路
这题对合法路径的要求中,有一个比较怪也难以维护的东西:要求不能走奇环。
如果没有这个东西,可以直接进行 \(O(n^2k)\) 的 \(\text{DP}\)。
但是考虑如何来解决奇环的限制?
一个很自然的想法是,如果给的是二分图,那么一条路径就等于在二分图左右两边的点中来回走。亦可以直接 \(\text{DP}\)。
这时候容易有一个基于这个想法的思路,对每个点随机染色,形成一张二分图。然后跑 \(\text{DP}\)。
这么做的正确概率是:\(\frac{1}{2^{k-1}}\),随机个 \(5000\) 次就能通过。
为什么想到随机化
我们为什么突然在这个想法中想到随机化?
首先,随机化本身就是来解决一些最值问题的。
更具体的,往往当一个东西难以直接维护,却容易在确定某些量之后计算,而且情况数量不多,取到最值概率不小时,我们会考虑随机化。
代码实现
点击查看代码
#include <bits/stdc++.h>
#define FL(i, a, b) for (int i = (a); i <= (b); ++i)
#define FR(i, a, b) for (int i = (a); i >= (b); --i)
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define Sz(v) ((int)(v).size())
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
constexpr int N = 85, K = 15, INF = 0x3f3f3f3f;
mt19937 Rand(chrono::steady_clock::now().time_since_epoch().count());
int n, k, ans = INF;
int c[N], mp[N][N], f[K][N];
void Work() {
c[1] = 0;
FL(i, 2, n) {
c[i] = Rand() & 1;
}
memset(f, 0x3f, sizeof(f));
f[0][1] = 0;
FL(i, 1, k) {
FL(u, 1, n) {
if (c[u] != (i & 1)) {
continue;
}
FL(v, 1, n) {
if (u == v) {
continue;
}
f[i][u] = min(f[i][u], f[i - 1][v] + mp[v][u]);
}
}
}
ans = min(ans, f[k][1]);
}
int main() {
scanf("%d %d", &n, &k);
FL(i, 1, n) {
FL(j, 1, n) {
scanf("%d", &mp[i][j]);
}
}
int T = 5000;
while (T--) {
Work();
}
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号