• Get Everything(状压DP)


    题意

    给定\(N\)个上锁的宝箱。有一个商店卖\(M\)个钥匙,每个钥匙的价格是\(a_i\),并且可以解锁\(b_i\)个宝箱,分别是\(c_{i, 1}, c_{i, 2}, \dots, c_{i, b_{i}}\)

    每个钥匙可以购买之后可以使用任意多次。

    问:要解锁所有宝箱需要花费多少钱?

    题目链接:https://atcoder.jp/contests/abc142/tasks/abc142_e

    数据范围

    \(1 \leq N \leq 12\)
    \(1 \leq M \leq 10^3\)

    思路

    观察到\(N\)的范围很小,因此考虑状压DP。

    \(f(i, j)\)表示使用前\(i\)个钥匙,解锁状态为\(j\)的宝箱,需要的最少花费。其中\(j\)为一个\(n\)位二进制数,如:\(10001\)表示解锁第\(1\)个和第\(5\)个宝箱。

    我们二重循环枚举使用前\(i\)个钥匙,以及用第\(i\)个钥匙之前的状态\(j\)

    • 如果不使用第\(i\)个钥匙,那么\(f(i, j) = \min \{f(i - 1, j), f(i, j)\}\)
    • 如果使用第\(i\)个钥匙,我们令\(c_i\)表示第\(i\)个钥匙可以解锁哪些钥匙。那么当前可以解锁的状态为\(k = j | c_i\),则\(f(i, k) = \min \{f(i, k), f(i - 1, j)+a_i\}\)

    \(c_i\)可以提前预处理。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1010, M = (1 << 12) + 10;
    
    int n, m;
    int a[N], c[N], f[N][M];
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i ++) {
            int x;
            scanf("%d%d", &a[i], &x);
            int tmp = 0;
            for(int j = 1; j <= x; j ++) {
                int t;
                scanf("%d", &t);
                tmp |= 1 << (t - 1);
            }
            c[i] = tmp;
        }
        memset(f, 0x3f, sizeof f);
        f[0][0] = 0;
        for(int i = 1; i <= m; i ++) {
            for(int j = 0; j < 1 << n; j ++) {
                f[i][j] = min(f[i][j], f[i - 1][j]);
                int t = c[i] | j;
                f[i][t] = min(f[i][t], f[i - 1][j] + a[i]);
            }
        }
        if(f[m][(1 << n) - 1] == 0x3f3f3f3f) printf("-1\n");
        else printf("%d\n", f[m][(1 << n) - 1]);
        return 0;
    }
    
  • 相关阅读:
    测试
    vue项目中使用 SheetJS / js-xlsx 导入文件
    vue项目中使用 SheetJS / js-xlsx 导出文件
    vue项目中使用canvas
    uniapp中mqtt的基本使用
    uniapp中vuex的基本使用
    uniapp如何在当前页面获取上个页面的变量、方法
    “微信小程序从分享卡片进入,第一次获取不到用户uid、第二次能获取到用户uid”解决方法
    vue-router的安装和使用
    vue-cli的安装步骤
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16440898.html
Copyright © 2020-2023  润新知