• 其他OJ 树型DP 技能树(未通过)


    http://www.cqoi.net:2012/JudgeOnline/problem.php?id=1380

    题意什么的都在里面,中文题目不用解释

    个人感觉是数据的问题,因为网上找遍了代码都不能通过,算了还是不纠结了

    代码写得也不好,无心机改了

    /*
    dp思想:dp[rt][p],当前节点rt,有p点,能获得的最大价值
    1.可以用一部分来升级当前的这个技能,升的级数不确定,但升级需要花费点数,花费的点数
      c<=p
    2.不升级当前,全部用于升级子树和兄弟。但注意,若不升级当前节点而且当前节点等级是0,那么
      其子树不能升级,只能升级其兄弟
    */
    
    #include <cstdio>
    #include <cstring>
    #define    N 25
    #define M 25
    #define LEN 25
    #define MAX 1010
    
    char skill[N][LEN];
    char parent[N][LEN];
    int fc[N],rb[N];
    int level[N];
    int cost[N][M];
    int val[N][M];
    int start[N];
    int sn;
    int P;
    int dp[N][MAX];
    
    int search(char *name)
    {
        if(name[0]=='\0') return 0;
        for(int i=1; i<=sn; i++)
            if(!strcmp(skill[i] , name))
                return i;
        return -1;
    }
    
    void input()
    {
        memset(fc,-1,sizeof(fc));
        memset(rb,-1,sizeof(rb));
        memset(level,0,sizeof(level));
        memset(cost,0,sizeof(cost));
        memset(val,0,sizeof(val));
        memset(skill,0,sizeof(skill));
    
        char name[LEN];
        for(int nn=1; nn<=sn; nn++)
        {
            int i;
            for(i=0; (name[i]=getchar())!='\n'; ) i++;
            name[i]='\0'; 
            strcpy(skill[nn] , name);
            //printf("%s\n",name);
    
            for(i=0; (name[i]=getchar())!='\n'; ) i++;
            name[i]='\0'; 
            strcpy(parent[nn] , name);
            //printf("%s\n",name);
    
            scanf("%d",&level[nn]);
            for(i=0; i<level[nn]; i++) 
                scanf("%d",&cost[nn][i]);
            for(i=0; i<level[nn]; i++)
                scanf("%d",&val[nn][i]);
            getchar();
        }
    
        scanf("%d",&P);
        for(int i=1; i<=sn; i++) 
            scanf("%d",&start[i]);
    
        for(int nn=1; nn<=sn; nn++)
        {
            int par=search(parent[nn]);
            int firson=fc[par];
            fc[par]=nn; rb[nn]=firson;
        }
    }
    
    int max(int x ,int y)
    {
        return x>y?x:y;
    }
    
    int cal(int rt ,int s ,int e)
    {
        int ans=0;
        for(int i=s; i<=e; i++)
            ans += cost[rt][i];
        return ans;
    }
    
    int sum(int rt ,int s,int e)
    {
        int ans=0;
        for(int i=s; i<=e; i++)
            ans += val[rt][i];
        return ans;
    }
    
    int dfs(int rt , int p)
    {
        if(rt<0) return 0;
        if(p==0) return dp[rt][p]=0;
        if(dp[rt][p]!=-1) return dp[rt][p];
        dp[rt][p]=0;
    
        for(int w=0; w<=p; w++) 
        {//先不给当前节点升级,将点数全部用于升级子树或兄弟
            int s1=0 ,s2=0;
            int firson=fc[rt] , bro=rb[rt];
            if(start[rt]) 
                s1=dfs(firson,p-w);
            s2=dfs(bro,w);
            dp[rt][p] = max(dp[rt][p] , s1+s2);
        }
        int c,v;
        for(int i=start[rt]; i<level[rt]; i++) //选择给当前节点升级,从它最初的等级开始
        {
            c=cal(rt,start[i],i); //升这么多级需要的点数
            v=sum(rt,start[i],i); //升这么多级能获得的价值
            if(c>p) break; //超过当前点数了直接跳出
            for(int w=0; w<=p-c; w++) //在剩下的p-c点数中分给孩子和兄弟
            {
                int s1=0 ,s2=0;
                int firson=fc[rt] , bro=rb[rt];
                s1=dfs(firson,p-c-w);
                s2=dfs(bro,w);
    
                dp[rt][p] = max(dp[rt][p] , s1+s2+v);
            }
        }
        return dp[rt][p];
    }
    
    void solve()
    {
        memset(dp,-1,sizeof(dp));
        dfs(fc[0],P);
        printf("%d\n",dp[fc[0]][P]);
    }
    
    int main()
    {
        while(scanf("%d",&sn)!=EOF)
        {
            getchar();
            input();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    【Java】LinkedHashMap
    【Java】 HashMap
    【译】Solr in Action 第三章
    【译】Solr in Action 第二章
    【译 】Solr in Action 第一章
    【Three.js】OrbitControl 旋转
    【翻译】JNA调用DLL
    .Net使用Redis详解之ServiceStack.Redis
    C#操作redis
    ECharts图介绍
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3013406.html
Copyright © 2020-2023  润新知