1017: [JSOI2008]魔兽地图DotR

耗费了我一上午的时间来肝这个题
考虑令 f [ i ] [ j ] [ k ] 表示第i个点花费了k的价值能提供j个道具用来合成的最大价值。。。
然后发现 d p 式子很容易推出来,但是发现这个复杂度嘛,不敢恭维 O ( 100 n m m )
左思右想也优化不了,然后去看了题解,,,发现真的是这个玄学的复杂度…
但是需要加优化,就是令 m x [ x ] 表示第 x 个点最多合成多少个,显然这个可以根据儿子或者其本身的价值推出来
c++代码如下:

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x ; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x ; i >= y; -- i)
using namespace std;
template<typename T>inline bool chkmax(T&x,T y) { return x < y ? x = y ,1 : 0; }
template<typename T>inline bool chkmin(T&x,T y) { return x > y ? x = y ,1 : 0; }
template<typename T>inline void read(T&x)
{
    x = 0;char c;int sign = 1;
    do { c = getchar(); if(c == '-') sign = -1; } while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); } while(isdigit(c));
    x *= sign;
}

const int N = 55,inf = 1e8 +7;
int nxt[N*N],to[N*N],w[N*N],head[N],tot;
inline void add(int x,int y,int val)
{
    w[tot] = val;
    nxt[tot] = head[x];
    to[tot] = y;
    head[x] = tot ++ ;
}

int f[N][101][2020],t[101][2020];
int n,m,c[N],d[N],p[N],mx[N]; 
bool rt[N];

void dfs(int x)
{
    if(head[x] == -1) 
    {
        rep(i,0,mx[x]) rep(j,0,m)
        {
            f[x][i][j] = p[x] * (min(d[x],j/c[x]) - i);
            if(f[x][i][j] < 0) f[x][i][j] = -inf;
        }
        return ;
    }

    mx[x] = 100;
    for(register int ii = head[x];~ii;ii = nxt[ii])
    {
        dfs(to[ii]);
        c[x] += c[to[ii]] * w[ii];
        if(x !=0)chkmin(mx[x],mx[to[ii]]/w[ii]);
    }

    if(x == 0) mx[x] = 0;
    else chkmin(mx[x],m / c[x]);
    for(register int ii = head[x];~ii;ii=nxt[ii])
    {
        int y = to[ii],val = w[ii];
        rep(i,0,mx[x]) rep(j,0,m) t[i][j] = -inf;
        rep(i,0,mx[x]) {if(i * val > mx[y]) continue;
        repd(j,m,0) repd(k,j,0)
        {
            chkmax(t[i][j],f[y][i*val][j - k] + f[x][i][k]);
            if(t[i][j] < 0) t[i][j] = -inf;
        }}
        rep(i,0,mx[x]) rep(j,0,m) f[x][i][j] = t[i][j];
    }

    repd(i,mx[x]-1,0) rep(j,0,m)
        chkmax(f[x][i][j] ,f[x][i + 1][j] + p[x]);

}

char op[2];
int main()
{
    memset(head,-1,sizeof head);
    read(n); read(m);
    rep(i,1,n)
    {
        read(p[i]); scanf("%s",op);
        if(op[0] == 'A')
        {
            int c;
            read(c);
            rep(j,1,c)
            {
                int x,y;
                read(x), read(y);
                add(i,x,y);
                rt[x] = 1;
            }
        }
        else read(c[i]), read(d[i]),mx[i] = min(d[i],m/c[i]);
    }

    rep(i,1,n) if(!rt[i]) add(0,i,0);
    dfs(0);

    cout << f[0][0][m];

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Tgotp/article/details/80003123