zoukankan      html  css  js  c++  java
  • Hackers' Crackdown UVA

    给出n个电脑,每个电脑连着n个服务,然后每个电脑都连着m个邻电脑,如果当前的电脑某个服务被断开了,相邻的电脑的服务也会被断开,每个电脑都只能操作一次,问你最多可以让多少种服务被断开。一种服务被断开的条件就是存在一个破坏第i个电脑的集合,这个集合扩散出去的集合是全集(......语文真的是......讲不出来)

    先把每个电脑和邻电脑的状态记录下来,把这个看成一个集合,然后那么我现在的问题就变成了用一些电脑的集合并起来使他变成全集。

    现在把n个电脑的可能状态全部枚举出来,然后看当前这些电脑最多可以影响多少电脑,把这种状态记录下来,然后在开始dp

    dp[电脑的所有可能状态] = 当前状态可以获得的最大方案数

    所以我现在可以枚举破坏电脑的状态,然后去找这个状态的子集,如果我的子集可以影响的范围是全集的话,那么我的dp状态就是dp[i] = max(dp[i], dp[i^j]+1),表示我可能从补集+1或者自己原本的最大值。

    #include<map>
    #include<ctime>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lowbit(x) (x & (-x))
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const double pi = 4.0*atan(1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 1 << 17;
    const int maxm = 40000;
    const int mod = 1000000007;
    using namespace std;
    
    int n, m, tol;
    int dp[maxn];
    int state[maxn];
    int num[20];
    
    void init() {
        memset(dp, 0, sizeof dp);
        memset(num, 0, sizeof num);
        memset(state, 0, sizeof state);
    }
    
    int main() {
        int cas = 1;
        while(scanf("%d", &n), n) {
            init();
            for(int i=0; i<n; i++) {
                num[i] = 1 << i;
                scanf("%d", &m);
                while(m--) {
                    int tmp;
                    scanf("%d", &tmp);
                    num[i] |= (1 << tmp);
                }
            }
            tol = 1 << n;
            for(int i=0; i<tol; i++) {
                state[i] = 0;
                for(int j=0; j<n; j++) {
                    if(i & (1 << j)) {
                        state[i] |= num[j];
                    }
                }
            }
            for(int i=0; i<tol; i++) {
                for(int j=i; j; j=(j-1) & i) {
                    if(state[j] == tol - 1) {
                        dp[i] = max(dp[i], dp[i^j] + 1);
                    }
                }
            }
            printf("Case %d: %d
    ", cas++, dp[tol-1]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    VS2005 Web安装程序 创建程序菜单组
    文件夹 文件 加入/去除 Everyone全控
    [转]asp.net 部署数据库、开始菜单、桌面快捷方式实例
    身边的贵人
    AppCode下的cs类 取得相关路径
    遭遇“windows已经阻止此软件因为无法验证发行者”
    成功不是忽悠
    关于 软件注册授权 防止被大面积免费扩散 的设想
    [转]获取机器的硬件信息(CPU ID序列号, 主板信息,硬盘序列号,系统信息)
    递交辞呈之后
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/10296759.html
Copyright © 2011-2022 走看看