高质量好题:NOI2006 网络收费
质量很高,题目很好,思路巧妙。
奈何这里空白太小,我写不下。
于是记录一下学到的一个最有用的思路:当dp转移存在某些优先级顺序依赖的时候,可以用 dfs 记录其中一个维度的状态,不仅好写,还能省很多空间。
例如这一题,如果不用dfs的话,就要用一个非常屎的把两维信息丢到一维储存的压缩方式,需要的时候再提取。
不失为一种好方法,但是很难调我写了,没调出来。
void dfs(int u,int now,int l=1,int r=(1<<n)){
if(l==r){
g[u][0]=c[u-(1<<n)+1][0],g[u][1]=c[u-(1<<n)+1][1];
for(ri x=now,v=u>>1;v;x>>=1,v>>=1){
if(x&1) g[u][1]+=f[u][v];
else g[u][0]+=f[u][v];
}
return ;
}
int len=(r-l+1);
int mid=l+r>>1;
dfs(lc,now<<1|1,l,mid),dfs(rc,now<<1|1,mid+1,r);
for(ri i=0;i<=len/2;++i){
g[u][i]=1e18;
for(ri j=0;j<=len/2&&j<=i;++j)
g[u][i]=min(g[u][i],g[lc][j]+g[rc][i-j]);
}
dfs(lc,now<<1,l,mid),dfs(rc,now<<1,mid+1,r);
for(ri i=len/2+1;i<=len;++i){
g[u][i]=1e18;
for(ri j=i-len/2;j<=len/2&&j<=i;++j)
g[u][i]=min(g[u][i],g[lc][j]+g[rc][i-j]);
}
}
用了 dfs 之后就非常清新而且好写了。