博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷 1273 有线电视网
阅读量:5895 次
发布时间:2019-06-19

本文共 1411 字,大约阅读时间需要 4 分钟。

我一直觉得这题的题解写的有问题

大多数题解都说他是分组背包

但是我觉得这并不是分组背包,与分组背包有差别

咱们先看看题

 

题意就是要在不亏本的情况下,使最多的叶子节点看到比赛

咱们来想想这题的思路

这是典型的树形dp

也是我做的第一道树形dp

我们考虑一下dp方程

我们设dp[i][j],表示以i为根节点,满足j个客户所能获得的最大值

如何转移?

dp[i][j]=max(dp[i][j-k]+dp[x][k],dp[i][j]) x为i的儿子节点

在dfs时就可以计算出每个节的孩子数

看看代码,有注释

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 const int N=3005; 9 struct node10 {11 int x,v;12 node(int xx,int vv)13 {14 x=xx,v=vv;15 }16 };17 vector
g[N];18 int n,m,k,x,y,d[N],dp[N][N];19 int dfs(int x)20 {21 if(x>n-m)22 {23 dp[x][1]=d[x];//到根节点这个点的值肯定为他自身的值24 return 1;25 }26 int sum=0,t;27 for(int i=0;i
0;j--)32 {33 for(int kk=1;kk<=t;kk++)//t为他的孩子的孩子节点个数34 {35 if(j-kk>=0)36 dp[x][j]=max(dp[x][j],dp[x][j-kk]+dp[g[x][i].x][kk]-g[x][i].v);//dp过程37 }38 }39 }40 return sum;41 }42 int main()43 {44 scanf("%d %d",&n,&m);45 int v=n-m;46 for(int i=1;i<=v;i++)47 {48 scanf("%d",&k);49 for(int j=1;j<=k;j++)50 {51 scanf("%d %d",&x,&y);52 g[i].push_back(node(x,y));//加边53 }54 }55 for(int i=n-m+1;i<=n;i++)56 scanf("%d",&d[i]);57 memset(dp,~0x3f,sizeof(dp));58 for(int i=1;i<=n;i++)59 dp[i][0]=0;//初始化,每个节点选0个孩子肯定是060 dfs(1);61 for(int i=m;i>=1;i--)62 {63 if(dp[1][i]>=0)//大于零就可以选64 {65 printf("%d\n",i);66 break;67 }68 }69 return 0;70 }

这题就解决了

转载于:https://www.cnblogs.com/wzrdl/p/9801806.html

你可能感兴趣的文章
小小神
查看>>
易宝典文章——怎样管理Exchange Server 2013的组命名策略
查看>>
linux 一些日常小应用纪录
查看>>
C# Websocket消息推送---GoEasy
查看>>
我的友情链接
查看>>
OpenGL ES 设置GLKView 背景透明
查看>>
XCode9 遇到的一些坑记录帖
查看>>
进程管理
查看>>
我的VIM配置(ubuntu)
查看>>
linux 常用配置文件
查看>>
cisco交换机配置练习疑难
查看>>
我的友情链接
查看>>
16、MariaDB工作中遇到的一部分报错的解决方法
查看>>
jdk的fastdebug版本是什么
查看>>
ConcurrentLinkedQueue cas实现分析
查看>>
在论坛中出现的比较难的sql问题:13(循环替换问题)
查看>>
简单的Samba服务器安装
查看>>
blog addr
查看>>
如何选择 Web 前端模板引擎?
查看>>
VMware 上Clone Ubuntu虚拟机后找不到eth0
查看>>