2020杭电多校(第四场)
收获
- 学到了一个神奇的建图——$x$ 坐标和 $y$ 坐标分两边,连线就是 $(x,y)$ 这个点。
1002 Blow up the Enemy
暴力枚举就好。比较谁赢就比较杀死对方时间的长短。
1 | #include<bits/stdc++.h> |
1003 Contest of Rope Pulling
转化问题为:$n+m$ 个物品,每个物品描述为 $(w_i,v_i)$,求 $\sum w_i=0$ 下 $\sum v_i$ 的最大值。
这是一个 $01$ 背包问题,$dp[i][j]=\max(dp[i-1][j],dp[i-1][j-w_i]+v_i)$,但是直接做是 $O(n\sum w_i)=O(10^9)$ 的,会 TLE
。
由于最后我们要的答案是 $dp[n][0]$,所以 $dp$ 过程中,第二维越大,就越不大可能拉回来了。所以我们随机搞一搞,设一个上界 $T$,不考虑 $j>T$ 或 $j<T$ 的情况。这一随机处理的可行性依赖于:随机排序后,序列前缀和的最大值足够小(小于 $T$)。具体证明看题解吧,我也不会啊~
1 | #include<bits/stdc++.h> |
另外,在 $dp$ 的过程中决定 for
的范围也能卡过去:
1 | #include<bits/stdc++.h> |
1004 Deliver the Cake
每个点拆成左手、右手两个点,跑最短路即可。
1 | #include<bits/stdc++.h> |
1005 Equal Sentences
为了满足题目要求,我们发现我们能做的操作只能是相邻两数进行交换。
于是设 $dp[i]$ 是前 $i$ 个数的方案数,那么:
- 若 $s_i=s_{i-1}$,$dp[i]=dp[i-1]$;
- 若 $s_i\neq s_{i-1}$,$dp[i]=dp[i-1]+dp[i-2]$.
1 | #include<bits/stdc++.h> |
1007 Go Running
在一条线上跑来跑去的很混乱,我们自然想到把 $(t_i,x_i)$ 画到二维直角坐标系里,那么问题转化成:用最少的斜上/斜下 $45^\circ$ 直线穿过所有点。斜着很难受,我们转换一下坐标系 $\begin{cases}x’=x+y\\y’=y-x\end{cases}$ 就把问题变成了:用最少的平行于坐标轴的线穿过所有点。
这可以转换成二分图——横坐标和纵坐标是二分图两部分,$x$ 向 $y$ 连边表示 $(x,y)$ 这个点,而二分图的点表示平行于 $y$ 或 $x$ 轴的直线。那么问题转化成了:选出最少的点覆盖所有边,就是二分图最小点覆盖问题,根据 $\textbf{Konig}$ 定理,等价于二分图最大流问题。
注意:这道题 $\textbf{Dinic}$ 必须要用当前弧优化,否则会 TLE
。
1 | #include<bits/stdc++.h> |
1011 Kindergarten Physics
出题人耍我们呐……在题设范围内,小球动不了多少,直接输出 $d$ 就行了……