bzoj1017: [JSOI2008]魔兽地图DotR

树形dp。

好坑的dp。不会。

f[i][j][k]表示第i件装备和它的基础装备一共花费j个金币且向上提供j个装备时能取得的最大的力量值。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 100 + 10;
const int maxm = 2000 + 10;
int g[maxn],v[maxm],next[maxm],eid;
int fa[maxn];
int f[maxn][maxn][maxm],tmp[maxm];
int lim[maxn],a[maxn],c[maxn],r[maxn];
int n,m,res;

void addedge(int a,int b) {
    v[eid]=b; next[eid]=g[a]; g[a]=eid++;
    fa[b]=a;    
}

bool update(int &x,const int &y) {
    if(y>x) {x=y; return 1;}
    return 0;
}

void solve(int u) {
    if(g[u]==-1) {
        lim[u]=min(lim[u],m/c[u]);
        for(int i=0;i<=lim[u];i++)
        for(int j=i;j<=lim[u];j++)
            if(update(f[u][i][j*c[u]],(j-i)*a[u]))
                update(res,f[u][i][j*c[u]]);
        return;
    }
    lim[u]=maxm;
    for(int i=g[u];~i;i=next[i]) {
        solve(v[i]);
        lim[u]=min(lim[u],lim[v[i]]/r[v[i]]);
    }
    for(int i=0;i<=lim[u];i++) f[u][i][0]=0;
    for(int i=g[u];~i;i=next[i]) 
    for(int j=0;j<=lim[u];j++) {
        for(int k=0;k<maxm;k++) tmp[k]=f[u][j][k];
        memset(f[u][j],-1,sizeof(f[u][j]));
        for(int k=0;k<=m;k++)
        for(int l=0;l<=k;l++)
        if(tmp[k-l]!=-1 && f[v[i]][j*r[v[i]]][l]!=-1) 
            if(update(f[u][j][k],tmp[k-l]+f[v[i]][j*r[v[i]]][l]))
                update(res,f[u][j][k]);
    }
    
    for(int i=1;i<=lim[u];i++)
    for(int j=0;j<i;j++)
    for(int k=0;k<=m;k++) 
        if(f[u][i][k]!=-1)
        if(update(f[u][j][k],(i-j)*a[u]+f[u][i][k]))
            update(res,f[u][j][k]); 
}
char op[10];

int main() {
    memset(g,-1,sizeof(g));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%d%s",&a[i],op);
        if(op[0]=='B') {    
            scanf("%d%d",&c[i],&lim[i]);
        }
        else {
            int t;
            scanf("%d",&t);
            for(int j=1,k;j<=t;j++) {
                scanf("%d",&k);
                addedge(i,k);
                scanf("%d",&r[k]);
            }
        }
    }
    memset(f,-1,sizeof(f));
    for(int i=1;i<=n;i++) if(!fa[i]) solve(i);
    printf("%d\n",res);
    return 0;    
}
posted @ 2016-07-06 15:53  invoid  阅读(421)  评论(0编辑  收藏  举报