本来是一道很水的树形DP题
设dp[i][j]表示,带着j个人去攻打以节点i为根的子树的最大收益
结果wa了一整晚
原因:
坑点1:
即使这个节点里面没有守卫,你如果想获得这个节点的收益,你还是必须派一个人去这个节点,不然谁帮你去拿收益?
坑点2:
题目说是从节点1开始攻打,然后我就以为给出的数据都是以1为根节点的,就没有加双向边
不过,
最后我加了双向边,然后还是wa了
又找了很久,最后发现是前向星的数组开小了
注意:数组开小了可能会返回wa,tle,re等等等等
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 5 using namespace std; 6 7 const int maxn=110; 8 9 int dp[maxn][maxn]; 10 int bug[maxn]; 11 int val[maxn]; 12 13 struct Edge 14 { 15 int to,next; 16 }; 17 Edge edge[maxn<<1]; 18 int head[maxn]; 19 int tot,n,m; 20 21 void init() 22 { 23 memset(head,-1,sizeof head); 24 tot=0; 25 } 26 27 void addedge(int u,int v) 28 { 29 edge[tot].to=v; 30 edge[tot].next=head[u]; 31 head[u]=tot++; 32 } 33 34 int solve(); 35 36 int main() 37 { 38 while(scanf("%d %d",&n,&m)){ 39 if(n==-1&&m==-1) 40 break; 41 init(); 42 for(int i=1;i<=n;i++){ 43 int u; 44 scanf("%d %d",&u,&val[i]); 45 bug[i]=(u+19)/20; 46 } 47 for(int i=1;i<n;i++){ 48 int u,v; 49 scanf("%d %d",&u,&v); 50 addedge(u,v); 51 addedge(v,u); 52 } 53 54 printf("%d\n",solve()); 55 } 56 return 0; 57 } 58 59 void dfs(int u,int pre) 60 { 61 if(bug[u]>m) 62 return ; 63 for(int i=bug[u];i<=m;i++) 64 dp[u][i]=val[u]; 65 for(int i=head[u];~i;i=edge[i].next){ 66 int v=edge[i].to; 67 if(v==pre) 68 continue; 69 dfs(v,u); 70 for(int j=m;j>=bug[u];j--){ 71 for(int k=1;k<=j-bug[u];k++){ 72 dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]); 73 } 74 } 75 } 76 } 77 78 int solve() 79 { 80 if(m==0) 81 return 0; 82 memset(dp,0,sizeof dp); 83 dfs(1,-1); 84 85 return dp[1][m]; 86 }
时间: 2024-10-05 04:27:44