• [JSOI2008]魔兽地图


    树上背包

    题目传送门

    首先,有没有哪位dalao 愿意告诉我为什么合成高级装备不需要附加金币,,

    好吧,这个不重要

    明确表示装备合成路线可以用一棵树来表示。一颗?傻乎乎的在下之前每次就只dp一棵树,不出意外的WA了,,在看几遍,好嘛,好像是个森林啊(泪奔)

    最容易想到的dp[x][i][j]是第x件买了i个,花了j元的最高力量。但是,,这样好像就成为不可做题了(欢迎各路dalao打脸,反正不是我说的[手动滑稽](偷偷扔出FYJ挡枪)),那么换一种思路,还是dp[x][i][j],但表示的是第x件装备,用i件合成上级装备(即至少买了i件),花费j元的力量。如果i是基础装备,转移方程就直接出来了:d[x][i][j*cost[x]]=power[x]*(j-i)。

     如果是高级装备呢?

    那就枚举它买多少件,以及它的子装备买多少件,直接暴力转移,n^2*times^2。看看时限,3s,完全不方

    在下代码比较丑,求各位不要介意

    #include<bits/stdc++.h>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<list>
    #include<set>
    #include<vector>
    #include<iostream>
    #define ll int
    #define re register
    #define inf 0x3f3f3f3f
    #define inl inline
    #define sqr(x) (x*x)
    //#define eps 1e-8
    #define debug printf("debug
    ");
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#pragma GCC optimize (2)
    //#pragma G++ optimize (2)
    using namespace std;
    //const ll mod;
    const ll MAXN=3e5+10;
    inl ll read() {
        re ll x = 0; re int f = 1;
        char ch = getchar();
        while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
        while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x * f;
    }
    inl char readc() {
        char ch=getchar();
        while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
        return ch;
    }
    inl void write(re ll x){
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
    inl void writeln(re ll x){
        if(x<0) {x=-x;putchar('-');}
        write(x); puts("");
    }
    inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
    inl void FR() {
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    }
    inl void FC() {
        fclose(stdin);
        fclose(stdout);
    }
    struct Node {
        ll u,v,w,nxt;
    }e[20005<<1];
    ll cnt,head[60],ssw[60],g[20005],cost[60],times[60];
    bool fl[60],in[60],vis[60];
    ll ans[20005];
    inl void adde(ll u,ll v,ll w) {
        e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;
        e[cnt].nxt=head[u];head[u]=cnt;
    }
    ll d[60][105][2005],n,m;
    void dp(ll x) {
        if(vis[x]) return ;vis[x]=1;
        if(!fl[x]) {//基础装备 
            times[x]=min(times[x],m/cost[x]);
            for(re ll i=times[x];~i;i--) {
                for(re ll j=i;j<=times[x];j++) {
                    d[x][i][j*cost[x]]=ssw[x]*(j-i);
                }
            }
            return ;
        }
        for(re ll h=head[x];h;h=e[h].nxt) {
            dp(e[h].v);cost[x]+=e[h].w*cost[e[h].v];
            times[x]=min(times[x],times[e[h].v]/e[h].w);
        }
        times[x]=min(times[x],m/cost[x]);
        for(re ll i=times[x];~i;i--) {
            for(re ll j=1;j<=m;j++) g[j]=-inf;g[0]=0;
            for(re ll h=head[x];h;h=e[h].nxt) {
                for(re ll k=m;~k;k--) {
                    re ll sst=-inf;
                    for(re ll l=0;l<=k;l++) {sst=max(sst,g[k-l]+d[e[h].v][i*e[h].w][l]);}
                    g[k]=sst;//花k元能到的最高力量 
                }
            }
            for(re ll j=0;j<=i;j++) {
                for(re ll l=0;l<=m;l++) {
                    d[x][j][l]=max(d[x][j][l],g[l]+ssw[x]*(i-j));
                }
            }
        }
    }
    int main(){
    //    FR();
        n=read(),m=read();
        memset(times,inf,sizeof(times));
        memset(d,-inf,sizeof(d));
        for(re ll i=1;i<=n;i++) {
            ssw[i]=read();
            char sj[3];scanf("%s",sj);
            if(sj[0]=='A') {
                fl[i]=1;re ll c=read();
                for(re ll j=1;j<=c;j++) {
                    re ll sx=read(),xs=read();
                    if(!in[sx]) in[sx]=1;
                    adde(i,sx,xs);
                }
            }
            else if(sj[0]=='B') {
                fl[i]=0;cost[i]=read();
                times[i]=read();
            }
            else puts("RE");
        }
        for(re ll i=1;i<=n;i++) {
            if(!in[i]) {//被坑无数次 
                dp(i);
                for(re ll j=m;~j;j--) {
                    for(re ll k=0;k<=j;k++) {
                        ans[j]=max(ans[j],ans[j-k]+d[i][0][k]);
                    }
                }
            }
        }
        writeln(ans[m]);
    //    FC();
        return 0;
    }
  • 相关阅读:
    Java设计模式—单例模式
    Java集合框架
    Java进程和线程
    Java IO
    Java异常类
    Java面向对象—抽象类和接口
    Java面向对象—多态
    Java面向对象—继承
    Java面向对象
    Java基础语法
  • 原文地址:https://www.cnblogs.com/20020723YJX/p/9348020.html
Copyright © 2020-2023  润新知