zoukankan      html  css  js  c++  java
  • codeforces 284 E. Coin Troubles(背包+思维)

    题目链接:http://codeforces.com/contest/284/problem/E

    题意:n种类型的硬币,硬币的面值可能相同,现在要在满足一些限制条件下求出,用这些硬币构成t面值的方案数;每个限制条件:a,b表示a种类型的硬币要大于b种类型的硬币;

    题解:显然如果哪些条件构成环的话就不存在直接输出0。那么可行的情况下要先预处理一下,假设a>b>c>d

    那么最少的选择方式是(3,2,1,0)这个必须先预处理一下,然后还有,假如增加a的数量,那么b,c,d的数

    量就不受影响,但是如果增加b的数量,那么a的数量肯定要增加,所以还要预处理一个num[i]表示改变i种硬币

    需要增加多少。然后就是完全背包了。

    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <queue>
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    const int M = 1e5 + 10;
    ll a[400] , num[400] , dp[M];
    int to[400] , pre[400];
    vector<int>vc[400];
    void dfs(int pos , int cnt) {
        vc[cnt].push_back(pos);
        if(to[pos] == -1)
            return ;
        dfs(to[pos] , cnt);
    }
    int main() {
        int n , q , t , u , v;
        scanf("%d%d%d" , &n , &q , &t);
        for(int i = 1 ; i <= n ; i++) {
            scanf("%I64d" , &a[i]);
            to[i] = -1;
            pre[i] = -1;
        }
        while(q--) {
            scanf("%d%d" , &u , &v);
            to[u] = v;
            pre[v] = u;
        }
        int count = 0;
        for(int i = 1 ; i <= n ; i++) {
            if(pre[i] == -1) {
                dfs(i , count);
                count++;
            }
        }
        ll sta = 0;
        int tot = 0;
        for(int i = 0 ; i < count ; i++) {
            int len = vc[i].size();
            tot += len;
            long long sum = 0;
            for(int j = 0 ; j < len ; j++) {
                int pos = vc[i][j];
                sum += a[pos];
                num[pos] = sum;
            }
            sum = 0;
            if(len > 1) {
                for(int j = 0 ; j < len - 1 ; j++) {
                    int pos = vc[i][j];
                    sum += a[pos];
                    sta += sum;
                }
            }
        }
        memset(dp , 0 , sizeof(dp));
        if(sta <= t && tot == n) {
            dp[sta] = 1;
            for(int i = 0 ; i < count ; i++) {
                int len = vc[i].size();
                for(int j = 0 ; j < len ; j++) {
                    int pos = vc[i][j];
                    for(int k = (int)max(sta , num[pos]) ; k <= t ; k++) {
                        dp[k] += dp[k - num[pos]];
                        dp[k] %= mod;
                    }
                }
            }
        }
        printf("%I64d
    " , dp[t] % mod);
        return 0;
    }
    
  • 相关阅读:
    (最大团) poj 3692
    (floyd+匈牙利算法) poj 3216
    (floyd+匈牙利算法) poj 2594
    (最小点覆盖) hdu 1054
    (最小点覆盖) hdu 4619
    (最小点覆盖) hdu 1498
    (匈牙利算法+贪心) hdu 3729
    (匈牙利算法) hdu 5093
    (匈牙利算法) bzoj 1059
    (二分+匈牙利算法) hdu 2236
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6804988.html
Copyright © 2011-2022 走看看