標籤:最大權值 spl ext while etc ubi names 遍曆 turn
一句話題意:一棵樹,一共n個點,每個點上有一個權值,求從1出發,走k步,最多能遍曆到的權值。可以往回走。
第一(二)道樹上背包題,先是看了dalao的題解,改了一點就過範例了。然而....TLE??? 改了挺久發現由於多組資料且沒有“0 0”的輸入,如果不在讀入的時候加“~”或“EOF”就會死迴圈,從而導致TLE。
狀態設計:設f[i][j][0/1]為以i為根的子樹上,走j步,能得到的最大權值(0/1的表示會在轉移方程中描述) 考慮:(此處參考[email protected] ,侵刪qwq)每個節點在最終答案中的類型:1,不經過;2,經過但不返回;3,經過且返回 (返回的定義是最終的停止節點不位於該節點的子樹中) 那麼可以進行轉移:
之後便是一些細節問題:給數組賦初值(從0開始!走0步),更新head數組。
實現還是比較簡單的啦。
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 7 int n,k,tot; 8 int w[300],head[300]; 9 int f[300][200][3]; 10 struct node{11 int to,next,val;12 }edge[300];13 14 void add(int x,int y)15 {16 edge[++tot].to=y;17 edge[tot].next=head[x];18 head[x]=tot;19 }20 21 void read(int &x)22 {23 x=0;24 char ch=getchar();25 bool flag=false;26 while(ch<‘0‘||ch>‘9‘) flag|=(ch==‘-‘),ch=getchar();27 while(ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();28 x=flag ? -x : x;29 }30 31 void TreeDp(int u,int fa)32 {33 for(int i=0;i<=k;i++) f[u][i][1]=w[u],f[u][i][0]=w[u];34 for(int i=head[u];i;i=edge[i].next)35 {36 int v=edge[i].to;37 if(v==fa) continue;38 TreeDp(v,u);39 for(int kk=k;kk>=0;kk--)40 for(int j=0;j<=kk;j++)41 {42 if(kk>=j+2) f[u][kk][0]=max(f[u][kk][0],f[v][j][0]+f[u][kk-j-2][0]);43 if(kk>=j+2) f[u][kk][1]=max(f[u][kk][1],f[v][j][0]+f[u][kk-j-2][1]);44 if(kk>=j+1) f[u][kk][1]=max(f[u][kk][1],f[v][j][1]+f[u][kk-j-1][0]);45 }46 }47 }48 49 void init()50 {51 memset(f,0,sizeof(f));52 memset(head,0,sizeof(head));53 tot=0;54 } 55 56 int main()57 {58 while(scanf("%d%d",&n,&k)!=EOF)59 {60 for(int i=1;i<=n;i++) read(w[i]);61 for(int i=1;i<=n-1;i++)62 {63 int x=0,y=0;64 read(x),read(y);65 add(x,y),add(y,x);66 }67 TreeDp(1,-1);68 printf("%d\n",max(f[1][k][0],f[1][k][1]));69 init();70 }71 return 0;72 }
View Code
小結:分類討論常常也是解題重要的突破口呐。
POJ2486 Apple Tree 【樹上背包】