• UVa 11825


    题目

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2925


    题意

    n个节点,每个节点都有完全相同的n项服务。

    每次可以选择一个节点,破坏该节点和相邻节点的某项服务。

    问最多能完全破坏多少服务?

    思路

    如刘书,

    直接枚举状态的子集

    注意元素个数为k的集合有C^k_n个子集,那么枚举的时间复杂度为sum{c^k_n * 2^k} = 3^n,当n=16时,3^n=4e7,可以承受。

    注意枚举子集可以通过substa = (substa - 1)&sta来做,子集的补集则为substa ^ sta。

    感想

    1. 一开始觉得枚举时间是2^2n,觉得不行,还是缺乏细致的计算

    代码

    #include <algorithm>
    #include <cassert>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <string>
    #include <tuple>
    #define LOCAL_DEBUG
    using namespace std;
    typedef pair<int, int> MyPair;
    const int MAXN = 16;
    const int MAXSTA = 1 << 16;
    int edges[MAXN][MAXN];
    int edgeCnt[MAXN];
    int vis[MAXN];
    int vis2[MAXSTA];
    int dp[MAXSTA];
    
    int main() {
    #ifdef LOCAL_DEBUG
        freopen("C:\Users\Iris\source\repos\ACM\ACM\input.txt", "r", stdin);
        //freopen("C:\Users\Iris\source\repos\ACM\ACM\output.txt", "w", stdout);
    #endif // LOCAL_DEBUG
        int n;
        for (int ti = 1; scanf("%d", &n) == 1 && n; ti++) {
            for (int i = 0; i < n; i++) {
                scanf("%d", edgeCnt + i);
                for (int j = 0; j < edgeCnt[i]; j++) {
                    scanf("%d", edges[i] + j);
                }
            }
            int maxsta = (1 << n) - 1;
            for (int sta = 0; sta <= maxsta; sta++) {
                memset(vis, 0, sizeof vis);
                for (int i = 0; i < n; i++) {
                    if (sta & (1 << i)) {
                        vis[i] = true;
                        for (int j = 0; j < edgeCnt[i]; j++) {
                            vis[edges[i][j]] = true;
                        }
                    }
                }
                bool fl = true;
                for (int i = 0; i < n; i++) {
                    if (!vis[i]) {
                        fl = false;
                    }
                }
                if (fl) {
                    dp[sta] = 1;
                }
                else {
                    dp[sta] = 0;
                }
                
            }
            for (int sta = 0; sta <= maxsta; sta++) {
                for (int subSta = sta; subSta != 0; subSta = (subSta - 1) & sta) {
                    dp[sta] = max(dp[sta], dp[sta ^ subSta] + dp[subSta]);
                }
    
            }
            printf("Case %d: %d
    ", ti, dp[maxsta]);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    CF700C Break Up
    CF865C Gotta Go Fast
    CF1559D2 Mocha and Diana (Hard Version)
    CF1500C Matrix Sorting
    排列计数机
    CSP-S 2021 退役记
    【做题记录】[NOIP2011 提高组] 观光公交
    【做题记录】构造题
    乱搞
    二维树状数组
  • 原文地址:https://www.cnblogs.com/xuesu/p/10434396.html
Copyright © 2020-2023  润新知