首页 > 代码库 > BZOJ1017: [JSOI2008]魔兽地图DotR
BZOJ1017: [JSOI2008]魔兽地图DotR
传送门
设$f[i][j][k]$表示对于第$i$个点,向父节点贡献$j$个已合成的装备,花费了$k$的代价,最多获得的力量值。
单纯的$f[i][j][k]$是很难转移的,主要原因是无法维护和其他儿子的关系。所以对于每个节点再搞一个$g[i][j]$表示当前点的前$i$个儿子花费为$k$可以获得的最大的力量值。
然后肯定要先更新$g[][]$再以$g[][]$来更新$f[][][]$。
列出$g[i][j]$的状态转移方程就是:
$g[cnt][k]=max \{ f[son][tol \times edge_v][j] + g[cnt-1][k-j] \}$
其中$tol$表示当前点总共要合成的装备。
然后根据$g[i][k]$来更新$f[i][j][k]$:
$f[i][j][k]= max \{ g[cnt_{max}][k]+(tol-j) \times Power_i \} $
然后就能愉快的转移了。
我看其他人的代码关于$tol$的枚举是递减的从而减少不必要的memset。不是很理解,希望神犇留言告诉我QAQ,不过直接memset也不会超时。
//BZOJ 1017//by Cydiater//2016.10.26#include <iostream>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <ctime>#include <cmath>#include <cstdlib>#include <cstdio>#include <iomanip>#include <bitset>using namespace std;#define ll long long#define up(i,j,n) for(int i=j;i<=n;i++)#define down(i,j,n) for(int i=j;i>=n;i--)#define cmax(a,b) a=max(a,b)#define cmin(a,b) a=min(a,b)const int MAXN=1e4+5;const int oo=1000000001;inline int read(){ char ch=getchar();int x=0,f=1; while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f;}int N,M,len=0,LINK[MAXN],f[55][105][2005],Power[MAXN],Cost[MAXN],LIM[MAXN],indu[MAXN],g[55][MAXN],ans=0;bool tag[MAXN];struct edge{ int y,next,v;}e[MAXN];namespace solution{ inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;} void init(){ memset(indu,0,sizeof(indu)); N=read();M=read(); up(i,1,N)LIM[i]=oo; up(i,1,N){ Power[i]=read();char ch;scanf("%c",&ch); tag[i]=(ch==‘A‘)?1:0; if(tag[i]){ int tmp=read(); while(tmp--){ int y=read(),v=read(); insert(i,y,v);indu[y]++; } }else{ Cost[i]=read();LIM[i]=read(); } } } void TreeDP(int node){ if(!tag[node]){ cmin(LIM[node],M/Cost[node]); up(i,0,LIM[node])up(j,0,i) f[node][j][i*Cost[node]]=Power[node]*(i-j); }else{ LIM[node]=oo; for(int i=LINK[node];i;i=e[i].next){ TreeDP(e[i].y);cmin(LIM[node],LIM[e[i].y]/e[i].v); Cost[node]+=e[i].v*Cost[e[i].y]; } cmin(LIM[node],M/Cost[node]); up(tol,0,LIM[node]){ int cnt=0; memset(g,-10,sizeof(g));g[0][0]=0; for(int i=LINK[node];i;i=e[i].next){ cnt++; up(j,0,M)up(k,0,j) cmax(g[cnt][j],g[cnt-1][j-k]+f[e[i].y][e[i].v*tol][k]); } up(j,0,tol)up(k,0,M)cmax(f[node][j][k],g[cnt][k]+(tol-j)*Power[node]); } } } void output(int node){ up(j,0,LIM[node])up(k,0,M)cmax(ans,f[node][j][k]); }}int main(){ freopen("input.in","r",stdin); using namespace solution; init(); memset(f,-10,sizeof(f)); up(i,1,N)if(indu[i]==0){ TreeDP(i); output(i); } cout<<ans<<endl; return 0;}
BZOJ1017: [JSOI2008]魔兽地图DotR
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。