树上背包
首先,有没有哪位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\n"); //#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; }
原文地址:https://www.cnblogs.com/20020723YJX/p/9348020.html
时间: 2024-10-11 06:14:06