当前位置:   article > 正文

第十三届安徽省大学生程序设计大赛_K基地安全(树形DP)_程序设计植被保护题

程序设计植被保护题

题目描述:

题目分析: 

这道题可以用树形dp来做,首先呢我们考虑dp的下界,不管是五边形,四边形还是三角形,最后都会被分成一条直线。

其次,我们要考虑对一个图形dp的方式,这道题我们选择按照编号顺序从左往右,从右往左,和从两头向中间三种方式,最后取答案的最小值。

代码:

  1. #include<bits/stdc++.h>
  2. #define N 200005
  3. using namespace std;
  4. int n;
  5. vector<int>g[N];
  6. int cur[N];
  7. struct DP{int l,r,lr;}dp[N];
  8. int tot,mid[N],ls[N],rs[N];
  9. int dfs(int l,int r){
  10. int p=++tot;
  11. if(l==r-1){
  12. dp[p].l = 1, dp[p].r = 1, dp[p].lr = 2;
  13. }
  14. else{
  15. mid[p]=g[l][++cur[l]]; // L 最小的一个邻接点是L+1, 所以可以保证g[l][++cur[l]]永远有意义
  16. //cout<<"分界点-------"<<"l="<<l<<",r="<<r<<", p="<<p<<", mid[p]="<< mid[p]<<",cur[l]="<<cur[l]<<endl;
  17. ls[p]=dfs(l,mid[p]);
  18. rs[p]=dfs(mid[p],r);
  19. dp[p].l=min(dp[ls[p]].l+dp[rs[p]].l,dp[ls[p]].lr+dp[rs[p]].l-1),// 左儿子和右儿子均从左边删顶点, 或者 左儿子左右删顶点+右儿子从左边删顶点
  20. dp[p].r=min(dp[ls[p]].r+dp[rs[p]].lr-1,dp[ls[p]].r+dp[rs[p]].r),// 左儿子和右儿子均从右边删顶点, 或者 右儿子左右删顶点+左儿子从右边删顶点
  21. dp[p].lr=min(dp[ls[p]].l+dp[rs[p]].r,dp[ls[p]].lr+dp[rs[p]].lr-1);// 左儿子和右儿子均从左右删顶点, 或者 左儿子从左边删顶点+右儿子从右边删顶点
  22. }
  23. return p;
  24. }
  25. int main(){
  26. scanf("%d",&n);
  27. for(int i=0;i<2*n-3;i++){
  28. int s,t;
  29. scanf("%d%d",&s,&t);
  30. if(s>t)swap(s,t);
  31. g[s].push_back(t);
  32. }
  33. for(int i=1;i<=n;i++)sort(g[i].begin(),g[i].end(), greater<int>()); // 邻接顶点从大到小
  34. dfs(1,n);
  35. dp[1].l=min(dp[1].l,dp[1].lr);
  36. printf("%d\n",min(dp[1].l,dp[1].r));
  37. return 0;
  38. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/590893
推荐阅读
相关标签
  

闽ICP备14008679号