zoukankan      html  css  js  c++  java
  • 01背包dp+并查集 Codeforces Round #383 (Div. 2)

    http://codeforces.com/contest/742/problem/D

    题目大意:有n个人,每个人有重量wi和魅力值bi。然后又有m对朋友关系,朋友关系是传递的,如果a和b是朋友,b和c是朋友,那么a和c就是朋友。现在,把所有能作为朋友的人放在一个集合里面。你现在要开一个party,这个party的容量为W,现在,你每次只能选择一个集合里面的一个人或者选择集合里面的所有人进入这个party。在满足总w <= W的情况下,总魅力值b最大,问魅力值最大是多少?

    思路:

    定义dp(i, j)表示目前是第i个集合,party里面的重量为j的最大魅力值。

    dp(i, j) = max(dp[i - 1][j], dp[i-1][j - 集合的总w(或集合的某个w)]) + 集合的总b(或集合中的某一个b)

    复杂度O(n*n)

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 1000 + 5;
    int dp[maxn][maxn];
    vector<pair<int, int> > subset[maxn];
    pair<int, int> f[maxn];
    int par[maxn];
    int n, m, w;
    
    int pfind(int x){
        if (par[x] == x) return x;
        return par[x] = pfind(par[x]);
    }
    
    map<int, int> id;
    int cnt = 0;
    int get_id(int x){
        if (id.count(x) == 0) id[x] = ++cnt;
        return id[x];
    }
    
    int main(){
        cin >> n >> m >> w;
        for (int i = 1; i <= n; i++) par[i] = i;
        for (int i = 1; i <= n; i++)
            scanf("%d", &f[i].fi);
        for (int i = 1; i <= n; i++)
            scanf("%d", &f[i].se);
        for (int i = 1; i <= m; i++){
            int u, v; scanf("%d%d", &u, &v);
            int pu = pfind(u), pv = pfind(v);
            par[pv] = pu;
        }
    
        for (int i = 1; i <= n; i++){
            int myid = get_id(pfind(i));
            subset[myid].pb(f[i]);
        }
    
        for (int i = 1; i <= cnt; i++){
            for (int j = w; j >= 0; j--){
                int totw = 0, totb = 0;
                dp[i][j] = dp[i - 1][j];
                for (int k = 0; k < subset[i].size(); k++){
                    pair<int, int> p = subset[i][k];
                    totw += p.fi, totb += p.se;
                    if (p.fi > j) continue;
                    dp[i][j] = max(dp[i][j], dp[i - 1][j - p.fi] + p.se);
                }
                if (totw <= j){
                    dp[i][j] = max(dp[i][j], dp[i - 1][j - totw] + totb);
                }
            }
        }
    
        int ans = 0;
        for (int i = 0; i <= w; i++)
            ans = max(ans, dp[cnt][i]);
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    CNN的学习记录
    softmax和softmax loss的学习记录
    Vue2.0 生命周期
    Vue methods 方法
    Vue2.0 全局操作 Vue.set
    Vue2.0 自定义指令 vuedirective
    Vue2.0 构造器的延伸 Vue.extend
    vue computed
    vuecli 脚手架分析
    h5表单介绍与案例
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6142076.html
Copyright © 2011-2022 走看看