POJ Apple Tree 題解(樹形dp+01揹包)
阿新 • • 發佈:2021-08-23
題目連結
題目大意
有一個樹,n個節點,第一個節點為根節點,每個點都有一個權值,每個點都可以移動到相鄰的點,給你樹的連線情況,求出,走k步最多獲得多少權值?
題目思路
主要考慮回頭的情況,所以不能簡單的設定\(dp[i][j]\)
\(dp[i][j][0]\)表示在子樹 i中最多走 j步最後還回到 i 能得到的最大蘋果數。
\(dp[i][j][1]\) 表示在子樹 i中最多走 j步最後不回到 i 能得到的最大蘋果數
然後再跑01揹包即可
程式碼
卷也卷不過,躺又躺不平#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #define se second #define debug cout<<"I AM HERE"<<endl; using namespace std; typedef long long ll; const int maxn=2e2+5,inf=0x3f3f3f3f,mod=1e9+7; const double eps=1e-6; int n,k; int a[maxn]; int dp[maxn][maxn][2]; vector<int> g[maxn]; void dfs(int u,int fa){ for(int i=0;i<=k;i++){ dp[u][i][0]=dp[u][i][1]=a[u]; } for(int a=0;a<g[u].size();a++){ int x=g[u][a]; if(x==fa) continue; dfs(x,u); for(int i=k;i>=1;i--){ for(int j=0;j<=i;j++){ if(i-j-2>=0) dp[u][i][0]=max(dp[u][i][0],dp[x][j][0]+dp[u][i-j-2][0]); if(i-j-1>=0) dp[u][i][1]=max(dp[u][i][1],dp[x][j][1]+dp[u][i-j-1][0]); if(i-j-2>=0) dp[u][i][1]=max(dp[u][i][1],dp[x][j][0]+dp[u][i-j-2][1]); } } } } signed main(){ while(scanf("%d%d",&n,&k)!=-1){ for(int i=1;i<=n;i++){ scanf("%d",&a[i]); g[i].clear(); for(int j=0;j<=k;j++){ dp[i][j][0]=dp[i][j][1]=0; } } for(int i=1,u,v;i<=n-1;i++){ scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dfs(1,-1); int ans=0; ans=max(ans,dp[1][k][0]); ans=max(ans,dp[1][k][1]); printf("%d\n",ans); } return 0; }