题解:
思路来自博客:http://www.ylzx8.cn/kaifayuyan/program/192149.html
dp[p][m]:表示在以p为根的子树中停留m个机器人的花费。把一棵子树看作是一个整体。
很好的树形dp,理解了好久。一定注意是要把一棵子数看作一个整体。
一开始,dfs刚到某个节点,如果没有儿子节点的话,那么机器人到此就都可以停了,dp[p][m]为0
如果发现了有一个儿子节点,那么考虑在这个儿子节点停留remain个机器人。
dp[p][k]+=dp[next][0]+cost*2; //子树son中没有停留机器人,那么意味全反回,最少是去一个所以最少反回一个
for(remain=1;remain<=k;remain++)
dp[p][k]=min(dp[p][k],dp[p][k-remain]+dp[next][remain]+remain*cost); //注:dfs到第一个儿子的时候,由于暂时没发现其余儿子,所以留在p节点的机器 // 人都不会有多余消耗
随着dfs的深入,每发现一个新儿子,那么更新时就要用考虑到前面所有儿子的状态进行转移。这是一个渐进的过程。
比如,在第二个儿子时,k=1,remain=1 的话,
dp[p][k]=min(dp[p][k],dp[p][k-remain]+dp[next][remain]+remain*cost);
用到的dp[p][k-remain]已经不再是0,因为首先必须把第一个儿子访问过再回到p节点。
所有儿子都dfs过之后,得到的dp[p][m]才不再变化。
思路:由于两条直线和坐标轴夹角为45度,且相互垂直,不妨把坐标系旋转45度,使得直线和坐标轴平行。解决最大值最小这类问题一般用二分来做,二分答案,看能否构造出答案出来。问题转化为能否将所有点分成两个部分,使得其中一部分的x值之差恒小于等于d,另一部分y值之差恒小于等于d,如果能那么答案d/2就存在,否则答案不存在,据此缩小答案范围。在判断答案是否存在的时候,将点按x坐标排序,从小到大枚举x的最小值,那么x的最大值是单调递增的,那么剩下的点由前p和和后q个构成,它们的纵坐标的最大差可以一次性预处理,然后O(1)得到。总复杂度n(log n + log maxans)
本题首先要解决的问题是如何让字符串读入回车,首先我们要定义一个字符串string s,然后用getline(cin,s[k])的方式输入即可。
注释分两种:// 和 /* */,每次碰到‘ / ‘都要判断下一个字符是什么,第一种需要从//到行尾都去掉,第二种需要把从/*到*/都去掉,要注意的是*/之后如果有回车是不能去掉的,这样去除注释以后应该要有一个空行。注意到这个问题再注意一下细节就可以顺利ac了。