• 树状DP


    紫皮,各种,非原创

    树状数组在我的理解就是在决策过程中具有层次关系,像是树一样,具有上下级关系或者上级对上级一定程度的限制条件

     uva 12186

    工人的请愿书

    下属中不小于 T% 的人签字时会签字递给上级,问至少需要多少人签字才能传给老板

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <cstdlib>
    #include <map>
    #include <queue>
    #include <vector>
    
    const int MAXN = 100000+ 10;
    const double ESP = 10e-8;
    const double Pi = atan(1.0) * 4;
    const int INF = 0xffffff;
    const int MOD = 2012;
    typedef long long LL;
    using namespace std;
    vector<int>sons[MAXN];
    int n,T;
    int dp(int u){
        if(sons[u].empty()){
            return 1;
        }
        int k = sons[u].size();
        vector<int>d;
        for(int i = 0;i < k;i++){
            d.push_back(dp(sons[u][i]));
        }
        sort(d.begin(),d.end());
        int c = (k*T - 1) / 100+ 1;
        int ans = 0;
        for(int i = 0;i < c;i++){
            ans += d[i];
        }
        return ans;
    }
    int main(){
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d%d",&n,&T)){
            if(!n && !T){
                break;
            }
            for(int i = 0;i <= n;i++){
                sons[i].clear();
            }
            for(int i = 1;i <= n;i++){
                int a;
                scanf("%d",&a);
                sons[a].push_back(i);
            }
            printf("%d
    ",dp(0));
        }
        return 0;
    }
    View Code

     poj 3442 / uva 1220 Party at Hali-Bula

    晚会邀请人,但是上下级不能在一起,求最多能邀请多少人,并且方案是否唯一

    d(u,1) 邀请了u,所以其下级不能邀请 所以d(u,1) = sum(d(v,0) );

    d(u,0) 没有邀请u,所以其下级,可以邀请也可以不邀请 则 d(u,0) = sum{ max( d(v,0),d(v,1) ) };

    f(u,0) 为 1表示不唯一,否则唯一

    f(u,1) 表示邀请了u,其方案是否唯一,当f(v,0)不唯一时,则f(u,1)必须不唯一

    f(u,0) 没邀请 u 的方案是否唯一,如果 d(v,1) == d(v,0) 或者 由其所取的值得f(v)决定

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <stack>
    #include <cctype>
    #include <string>
    #include <queue>
    #include <map>
    #include <set>
    
    using namespace std;
    
    const int INF = 0xffffff;
    const double ESP = 10e-8;
    const double Pi = 4 * atan(1.0);
    const int MAXN =  200 + 10;
    const long long MOD =  1000000007;
    const int dr[] = {1,0,-1,0,-1,1,-1,1};
    const int dc[] = {0,1,0,-1,1,-1,-1,1};
    typedef long long LL;
    
    LL gac(LL a,LL b){
       return b?gac(b,a%b):a;
    }
    int n;
    int d[MAXN][2];
    int child[MAXN];
    bool f[MAXN][2];
    int cnt;
    map<string,int>m;
    vector<int>G[MAXN];
    int getNum(string str){
        int a;
        if(m.count(str)){
            a = m[str];
        }
        else{
            a = cnt;
            m[str] = cnt++;
        }
        return a;
    }
    void dp(int r){
        if(!G[r].size()){ //没有孩子
            d[r][1] = 1;//如果选择r能获得的最大值
            d[r][0] = 0; //如果不选择r获得的最大值
    //        f[r][1] = 1;
    //        f[r][0] = 1;
            return;
        }
        d[r][1] = 1; //如果选择了r则包含r这个员工
        bool flag = 1;
    //    f[r][0] = 1;
        int len = G[r].size();
        for(int l = 0;l < len;l++){
            dp(G[r][l]);
            int i = G[r][l];
            if(f[i][0]){
                f[r][1] = 1;
            }
            d[r][1] += d[i][0];
            if(d[i][0] > d[i][1]){
                d[r][0] += d[i][0];
                if(f[i][0])
                    f[r][0] = 1;
            }
            else{
                d[r][0] += d[i][1];
                if(d[i][1] == d[i][0] || f[i][1])
                    f[r][0] = 1;
            }
    //        if(G[r][i]){
    //            dp(i);
    //            if(f[i][0]){
    //                f[r][1] = 1;
    //            }
    //            d[r][1] += d[i][0];
    //            if(d[i][0] > d[i][1]){
    //                d[r][0] += d[i][0];
    //                if(f[i][0])
    //                    f[r][0] = 1;
    //            }
    //            else{
    //                d[r][0] += d[i][1];
    //                if(d[i][1] == d[i][0] || f[i][1])
    //                    f[r][0] = 1;
    //            }
    ////            d[r][1] += d[i][0]; //如果选择了r这其下级不能选择
    ////            if(!f[i][0]){
    ////                flag = 0;
    ////            }
    ////            if(d[i][0] == d[i][1]){
    ////                f[i][0] = 0;
    ////                d[r][0] += d[i][0];
    ////            }
    ////            else if(d[i][0] > d[i][1]){
    ////                d[r][0] += d[i][0];
    ////                if(!f[i][0]){
    ////                    f[r][0] = 0;
    ////                }
    ////            }
    ////            else{
    ////                d[r][0] += d[i][1];
    ////                if(!f[i][1]){
    ////                    f[r][0] = 0;
    ////                }
    ////            }
    //
    //        }
    //    }
    //    if(flag){
    //        f[r][1] = 1;
        }
        return;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("inpt.txt","r",stdin);
       // freopen("output.txt","w",stdout);
    #endif
        while(~scanf("%d",&n) && n){
            cnt = 1;
            memset(child,0,sizeof(child));
            memset(f,0,sizeof(f));
            memset(d,0,sizeof(d));
            string str1;
            string str2;
            m.clear();
            cin >> str1;
            m[str1] = cnt++;
            int a,b;
            for(int i = 0;i <= n;i++){
                G[i].clear();
            }
            for(int i = 1;i < n;i++){
                cin >> str1 >> str2;
                a = getNum(str1);
                b = getNum(str2);
                G[b].push_back(a);
            }
            dp(1);
            if(d[1][0] == d[1][1]){
                printf("%d No
    ",d[1][0]);
            }
            else if(d[1][0] > d[1][1]){
                printf("%d %s
    ",d[1][0],!f[1][0]?"Yes":"No");
            }
            else{
                printf("%d %s
    ",d[1][1],!f[1][1]?"Yes":"No");
            }
        }
        return 0;
    }
    View Code

    poj 3398 Perfect Service / uva 1218

    联通的计算机,从中间抽取几台电脑充当服务器,使每台电脑恰好有一台服务器相连,求最小的服务器数目

    d(u,0) u是服务器,其子节点既可以是服务器,也可以不是服务器

    d(u,1) u 不是服务器,但是其父亲是服务器,其儿子一定不是服务器

    d(u,2) u不是服务器,其父亲也不是服务器,u恰好一个v是服务器

    d(u,0) = sum{min(d(v,0),d(v,1)) } + 1;

    d(u,1) = sum{d(v,2)};

    d(u,2) = sum{d(vv,2)} = min(d(u,1)- d(v,2) + d(v,0)) //其某一个子节点为服务器

    因为是无向树所以需要vis标记

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    
    const int MAXN = 10000 + 10;
    const int INF = 0xffffff;
    const int mod = 1000007;
    const double Pi = atan(1.0)*4;
    const double ESP = 10e-8;
    
    using namespace std;
    vector<int>G[MAXN];
    int d[MAXN][4];
    bool vis[MAXN];
    int n;
    void dp(int u){
        vis[u] = 1;
        int len = G[u].size();
        d[u][0] = 1;  //u是服务器,其子节点既可以是服务器,也可以不是,其父节点可以是服务器,也可以不是
        d[u][1] = 0; //u不是服务器,但是u父亲是服务器,所以其子节点都不是服务器
        d[u][2] = INF; // u,和u的父亲都不是服务器,所以u的子节点必须有点是服务器
        vector<int>arr;
        for(int i = 0;i < len;i++){
            int v = G[u][i];
            if(vis[v])
                continue;
            dp(v);
            arr.push_back(v);
            d[u][0] += min(d[v][0],d[v][1]);  // 子节点既可以是服务器又可以不是服务器所以取最小值
            d[u][1] += d[v][2]; // u不是服务器,子节点不是服务器,所以等于d[v][2]父亲和其本身都不是服务器的相加
        }
        len = arr.size();
        for(int i = 0;i < len;i++){
            int v = arr[i];
            d[u][2] = min(d[u][2],d[u][1] - d[v][2] + d[v][0]);
        }
    }
    int main(){
       // freopen("input.txt","r",stdin);
        while(~scanf("%d",&n)){
            for(int i = 0;i <= n;i++){
                G[i].clear();
            }
            memset(vis,0,sizeof(vis));
            memset(d,0,sizeof(d));
            for(int i = 1;i < n;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                G[b].push_back(a);
                G[a].push_back(b);
            }
            dp(1);
            int ans = INF;
            ans = min(d[1][0],d[1][2]);
            printf("%d
    ",ans);
            scanf("%d",&n);
            if(n < 0)
                break;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    SM3国密算法标准中两个实例的实现
    2017-2018《网络攻防技术》第十周作业
    2017-2018《网络攻防技术》第九周作业
    2017-2018网络攻防技术第八周作业
    第十一周作业
    指针学习
    2017-2018第七周网络攻防作业
    2017-2018网络攻防第六周作业
    2017-2018网络攻防第五周作业
    spark要我命_2_算了,不起标题了
  • 原文地址:https://www.cnblogs.com/hanbinggan/p/4422439.html
Copyright © 2020-2023  润新知