bzoj 4711 小奇挖矿 ——“承诺”类树形dp
生活随笔
收集整理的這篇文章主要介紹了
bzoj 4711 小奇挖矿 ——“承诺”类树形dp
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目:https://www.lydsy.com/JudgeOnline/problem.php?id=4711
對“承諾”有了更深的了解。
向外和向內要區分,所以 f [ i ][ j ] 表示根向外 j 步有倉庫;g[ i ][ j ]表示根向內 j 步有倉庫。
轉移的時候要注意,要保證承諾的那個地方確實有倉庫;通過 cr 之前的孩子 或 當前孩子 的那個地方的承諾來保證;剩下的部分不用保證那兒有倉庫,用自己的最小值轉移即可;
一棵子樹如果承諾自己內部某個地方有倉庫,就一定已經有了;但承諾外部的某個地方有倉庫卻只是承諾;所以可以對 g[ ][ ] 取min來做那個隨便的轉移,卻不能隨便對待 f [ ][ ]。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=205,INF=1e9; int n,d[N],K,hd[N],xnt,to[N<<1],nxt[N<<1]; int f[N][N],g[N][N],mn[N]; void add(int x,int y) {to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt; } void dfs(int cr,int fa) {for(int i=1;i<n;i++)f[cr][i]=d[i],g[cr][i]=INF;f[cr][n]=g[cr][n]=INF;f[cr][0]=g[cr][0]=K; mn[cr]=K;//mn[cr]=Kfor(int i=hd[cr],v;i;i=nxt[i])if((v=to[i])!=fa){dfs(v,cr);for(int j=0;j<n;j++){if(j)g[cr][j]=min(g[cr][j]+min(f[v][j+1],mn[v]),g[v][j-1]+min(mn[cr],f[cr][j]));else g[cr][j]+=min(f[v][j+1],mn[v]);f[cr][j]=min(f[cr][j]+min(mn[v],f[v][j+1]),f[v][j+1]+mn[cr]);//printf("f[%d][%d]=%d g[%d][%d]=%d\n",cr,j,f[cr][j],cr,j,g[cr][j]); }mn[cr]=g[cr][0];for(int j=1;j<n;j++)min(mn[cr],g[cr][j]);}mn[cr]=g[cr][0];for(int i=1;i<n;i++)mn[cr]=min(mn[cr],g[cr][i]); } int main() {scanf("%d%d",&n,&K);for(int i=1;i<n;i++)scanf("%d",&d[i]);for(int i=1,u,v;i<n;i++){scanf("%d%d",&u,&v);add(u,v);}dfs(1,0);printf("%d\n",min(mn[1],f[1][0]));return 0; }?
轉載于:https://www.cnblogs.com/Narh/p/9754402.html
總結
以上是生活随笔為你收集整理的bzoj 4711 小奇挖矿 ——“承诺”类树形dp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 线程安全
- 下一篇: HihoCoder#1509 : 异或排