zoukankan      html  css  js  c++  java
  • POJ 3345 Bribing FIPA 树形DP

    题目链接: POJ 3345 Bribing FIPA

    题意:

             一个国家要参加一个国际组织,  需要n个国家投票,  n个国家中有控制和被控制的关系, 形成了一颗树.

           比如: 国家C被国家B控制, 国家B被国家A控制, 那么B , C 会跟着A投同一家国家. 而要有些国家给它投票,

           就得用若干钻石去贿赂那些国家. 最后问, 要到至少有m个国家投它的票, 最少需要多少钻石.

    分析: 对于每一个结点只有两种状态, 选与不选, 所以dp方程里加上一维即可.

          dp[i][j][k], 表示在i的子结点中,选j个最少需要的钻石数, 另k=1表示选i本身,k=0表示不选

         dp[cnt][j+k][0] = min( dp[cnt][j+k][0], dp[cnt][j][0] + min(dp[son][k][0],dp[son][k][1]) );

          

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<map>
    using namespace std;
    const int inf=0xFFFFFFF;
    vector<string>N[205];
    vector<int>M[205];
    map<string,int>Map;
    int h[205],dp[205][205][2]; ///  dp[i][j][k] k=0表示不选i,反之则选
    int n,m;
    void Init(){
        for(int i=0;i<=n;++i){
            N[i].clear();
            M[i].clear();
            for(int j=0;j<=n;++j)
                dp[i][j][1]=dp[i][j][0]=inf;
        }
        memset(h,0,sizeof(h));
    }
    void DFS(int cnt){
        int len=M[cnt].size();
        h[cnt]=len;
        for(int i=0;i<len;++i)
            DFS(M[cnt][i]),h[cnt]+=h[M[cnt][i]];
        for(int i=2;i<=min(m,h[cnt])+1;++i) 
            dp[cnt][i][1]=dp[cnt][1][1];   ///贿赂了cnt,就不用贿赂它的子结点
        dp[cnt][0][0]=0;
        for(int i=0;i<len;++i){
            int son=M[cnt][i];
            for(int j=m; j>=0; --j)
                for(int k=m-j; k>=0; --k)
                    dp[cnt][j+k][0]=min(dp[cnt][j+k][0],dp[cnt][j][0]+min(dp[son][k][0],dp[son][k][1]));
        }
    }
    int main(){
        while(cin>>n>>m){
            Init();
            for(int i=1;i<=n;++i){
                string s; cin>>s>>dp[i][1][1];
                Map[s]=i;
                char c; scanf("%c",&c);
                while(c!='
    '){
                    cin>>s; 
                    N[i].push_back(s);
                    scanf("%c",&c);
                }
            }
            for(int i=1;i<=n;++i){
                int len=N[i].size();
                for(int j=0;j<len;++j){
                    string s=N[i][j];
                    M[i].push_back(Map[s]);
                    h[Map[s]]=1;
                }
            }
            for(int i=1;i<=n;++i)
                if(h[i]==0) M[0].push_back(i);
            memset(h,0,sizeof(h));
            DFS(0);
            cout<<min(dp[0][m][1],dp[0][m][0])<<endl;
        }
        return 0;
    }
    
    /*
    
    7 3
    A 7 B C
    B 5 D E
    C 6 F G
    D 1
    E 2
    F 3
    G 4
    
    5
    */
    
    
    



  • 相关阅读:
    Cocos2d JS 之消灭星星(二) 工具类开发
    Cocos2d JS 之消灭星星(三) 进入游戏过渡场景
    Cocos2d JS 之本地存储(localStorage)
    Cocos2d JS 之消灭星星(—) 游戏初始化场景的建立
    小程序的1024KB
    小程序来了(下篇)
    小程序来了(上篇)
    那些年,让我们一起着迷的Spring
    小程序之信息触手可及
    史诗手册!微信小程序新手自学入门宝典!
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3249400.html
Copyright © 2011-2022 走看看