官方题解|帕罗蒂克
2024-12-15 22:05:32
发布于:浙江
40阅读
0回复
0点赞
题目解析
状态压缩动态规划
定义 为第 位朋友,已经经过的站点集合为 ,此时位于车站 的可行性。
那么我们就可以对每一位朋友分开考虑,并使用状态压缩动态规划,在 的时间复杂度内,计算出上述 数组。
然后我们定义 表示,经过 次移动,位于车站 的朋友的集合。根据已经得出的 数组,我们可以很容易计算出 数组。
最后根据 中的存储的集合是否为所有朋友的全集,来判断,是否可以在站点 汇合即可。
AC代码
#include <bits/stdc++.h>
constexpr int N = 15;
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int n, m, k;
std::cin >> n >> m >> k;
std::vector<int> a(k);
for (auto &x : a) std::cin >> x, --x;
std::vector<std::vector<int>> g(n);
for (int i = 0; i < m; ++i) {
int u, v;
std::cin >> u >> v, --u, --v;
g[u].push_back(v);
g[v].push_back(u);
}
int dp[N][1 << N][N]{};
for (int i = 0; i < k; ++i)
dp[i][1 << a[i]][a[i]] = 1;
for (int i = 0; i < k; ++i)
for (unsigned mask = 0; mask < (1u << n); ++mask)
for (int j = 0; j < n; ++j) if (dp[i][mask][j])
for (auto &nj : g[j]) if (~mask >> nj & 1)
dp[i][mask | 1 << nj][nj] = 1;
int turn[N + 1][N]{};
for (int i = 0; i < k; ++i)
for (unsigned mask = 0; mask < (1u << n); ++mask)
for (int j = 0; j < n; ++j) if (dp[i][mask][j])
turn[__builtin_popcount(mask)][j] |= 1 << i;
for (int step = 0; step <= n; ++step)
for (int i = 0; i < n; ++i)
if (turn[step][i] == (1 << k) - 1) {
std::cout << i + 1 << '\n';
return 0;
}
std::cout << -1 << '\n';
return 0;
}
这里空空如也
有帮助,赞一个