NOIP2017进步组.宝藏

[复制链接]
发表于 2025-10-3 21:36:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
标题

529. 宝藏

算法标签: 状态压缩                                   d                         p                              dp                  dp, 位运算, 贪心

思绪


代价便是                                   长度                         ×                         当前点的深度                              长度 \times 当前点的深度                  长度×当前点的深度, 求代价的最小值, 直接想法是                                   f                         [                         i                         ]                         [                         j                         ]                         [                         k                         ]                              f[j][k]                  f[j][k]表现整个聚集状态是                                   i                              i                  i, 末了一层状态是                                   j                              j                  j, 由于末了一层状态也要取决于上一层状态, 上一层状态是                                   k                              k                  k的最小代价, 但是时间复杂度会爆炸, 空间也会爆炸, 须要优化
算状态的时间只能和前一层相连, 只能连向上一层的点, 但是我们思量是否可以连到前面全部的点, 由于须要连最短边, 因此着实也是毗连到                                   i                         −                         1                              i - 1                  i−1层的点, 也就不须要毗连到上一层的点, 因此我们重新思量状态表现
                                    f                         [                         i                         ]                         [                         j                         ]                              f[j]                  f[j]选择的点的聚集是                                   i                              i                  i而且树的高度是                                   j                              j                  j的全部方案的最小代价, 按照末了一层的状态举行聚集的分别, 假设末了一层的状态是                                   k                              k                  k,                                    f                         [                         i                         ]                         [                         j                         ]                         =                         m                         i                         n                         (                         f                         [                         i                         ⊕                         k                         ]                         [                         j                         −                         1                         ]                         )                         +                         w                              f[j] = min(f[i \oplus k][j - 1]) + w                  f[j]=min(f[i⊕k][j−1])+w
代码

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. using namespace std;
  5. const int N = 12, M = 1 << N, INF = 0x3f3f3f3f;
  6. int n, m;
  7. int d[N][N], f[M][N];
  8. int g[M];
  9. int main() {
  10.         ios::sync_with_stdio(false);
  11.         cin.tie(0), cout.tie(0);
  12.         cin >> n >> m;
  13.         memset(d, 0x3f, sizeof d);
  14.         for (int i = 0; i < n; ++i) d[i][i] = 0;
  15.         for (int i = 0; i < m; ++i) {
  16.                 int u, v, w;
  17.                 cin >> u >> v >> w;
  18.                 u--, v--;
  19.                 d[u][v] = d[v][u] = min(d[u][v], w);
  20.         }
  21.         // 统计状态i能转移到的状态
  22.         for (int i = 0; i < 1 << n; ++i) {
  23.                 for (int j = 0; j < n; ++j) {
  24.                         if (i >> j & 1) {
  25.                                 for (int k = 0; k < n; ++k) {
  26.                                         if (d[j][k] != INF) g[i] |= 1 << k;
  27.                                 }
  28.                         }
  29.                 }
  30.         }
  31.         memset(f, 0x3f, sizeof f);
  32.         for (int i = 0; i < n; ++i) f[1 << i][0] = 0;
  33.         for (int i = 1; i < 1 << n; ++i) {
  34.                 for (int j = i - 1 & i; j; j = j - 1 & i) {
  35.                         if ((g[j] & i) == i) {
  36.                                 int pre = i ^ j, cost = 0;
  37.                                 for (int k = 0; k < n; ++k) {
  38.                                         if (pre >> k & 1) {
  39.                                                 int val = INF;
  40.                                                 for (int l = 0; l < n; ++l) {
  41.                                                         if (j >> l & 1) val = min(val, d[k][l]);
  42.                                                 }
  43.                                                 cost += val;
  44.                                         }
  45.                                 }
  46.                                 for (int k = 1; k < n; ++k) f[i][k] = min(f[i][k], f[j][k - 1] + k * cost);
  47.                         }
  48.                 }
  49.         }
  50.         int res = INF;
  51.         for (int i = 0; i < n; ++i) res = min(res, f[(1 << n) - 1][i]);
  52.         cout << res << "\n";
  53.         return 0;
  54. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表