bzoj1017: [JSOI2008]魔獸地圖DotR
阿新 • • 發佈:2018-07-08
href else code 枚舉 num memset its void har
題目鏈接
bzoj1017: [JSOI2008]魔獸地圖DotR
題解
設dp[i][j][k]表示以i為根的子樹中,有j個i節點用於和成上層,花費為k的最大收益
枚舉合成l個i節點,然後用剩余的錢在子樹中制造一些別的power
g[i][j]表示對於當前子樹的前i棵子樹花費j能得到的最大收益
得到g[i][j] = g[i - 1][k] + dp[v][need[v] * l][j - k] //註意,這裏的已經轉移保證了能合成上層l個
dp[x][j][k] = max(g[totson][k]))
最後背包合並
註意合法裝態轉移
代碼
/* 設dp[i][j][k]表示以i為根的子樹中,有j個i節點用於和成上層,花費為k的最大收益 枚舉合成l個i節點,然後用剩余的錢在子樹中制造一些別的power g[i][j]表示對於當前子樹的前i棵子樹花費j能得到的最大收益 得到g[i][j] = g[i - 1][k] + dp[v][need[v] * l][j - k] //註意,這裏的已經轉移保證了能合成上層l個 dp[x][j][k] = max(g[totson][k])) 最後背包合並 註意合法裝態轉移 */ #include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();} while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); return x * f; } #define INF 1000000007 int n,m; const int maxn = 87; const int maxm = 2007; int limit[maxn],cost[maxn],power[maxn]; struct node { int v,next,w; }edge[20007]; int deg[maxn]; int dp[maxn][maxn * 2][maxm]; int g[maxn][maxm]; int num,head[maxn << 1]; void add_edge(int u,int v,int w) { edge[++ num].v = v;edge[num].w = w; edge[num].next = head[u]; head[u] = num; } void dfs(int x) { if(!head[x]) { for(int i = 0;i <= limit[x];++ i) for(int j = 0;j <= i;++ j) dp[x][j][i * cost[x]] = (i - j) * power[x]; return ; } limit[x] = INF; for(int i = head[x];i;i = edge[i].next) { int v = edge[i].v; dfs(v); limit[x] = std::min(limit[x],limit[v] / edge[i].w); cost[x] += cost[v] * edge[i].w; } limit[x] = std::min(limit[x],m / cost[x]); memset(g,-0x3f3f3f3f,sizeof g); g[0][0] = 0; // printf("%d\n",g[1][1]); int tmp = 0,tot = 0; for(int l = limit[x];l >= 0;-- l) { tot = 0,tmp = 0; for(int v,i = head[x];i;i = edge[i].next) { tot ++; v = edge[i].v; //tmp += cost[v] * edge[i].w; for(int j = 0/*tmp*/;j <= m;++ j) for(int k = 0/*tmp*/;k <= j;++ k) g[tot][j] = std::max(g[tot][j],g[tot - 1][k] + dp[v][edge[i].w * l][j - k]); } for(int i = 0;i <= l;++ i) for(int k = 0;k <= m;++ k) dp[x][i][k] = std::max(dp[x][i][k],g[tot][k] + power[x] * (l - i)); } } int h[maxn][maxm]; int main() { memset(dp,-0x3f3f3f3f,sizeof dp); n = read(),m = read(); char op[10]; for(int a,b,c,d,i = 1;i <= n;++ i) { power[i] = read(); scanf("%s",op); if(op[0] == 'A') { b = read(); for(int j = 1;j <= b;++ j) { c = read(),d = read(); add_edge(i,c,d); deg[c] ++; } } else { cost[i] = read(),limit[i] = read(); if(cost[i]) limit[i] = std::min(limit[i],m / cost[i]); } } int tot = 0; for(int x = 1;x <= n;++ x) { if(!deg[x]) { dfs(x); tot ++; for(int i = 0;i <= m;++ i) for(int j = 0;j <= i;++ j) { for(int k = 0;k <= limit[x];++ k) { h[tot][i] = max(h[tot][i],h[tot - 1][j] + dp[x][k][i - j]); } } } } int ans = 0; for(int i = 0;i <= m;++ i) ans = std::max(ans,h[tot][i]); printf("%d\n",ans);
bzoj1017: [JSOI2008]魔獸地圖DotR