第一题:模拟
直接按题目描述模拟,用一个队列实现。
由于是非负整数,所以要记得开0下标
第二题:动态规划
首先问题只与所用卡片的个数和位置有关,所以可以根据这个设计状态进行动态规划
记f[i, j, k, l]表示用了i个1步的卡片,j个2步的卡片,k个3步的卡片,l个4步的卡片所获得的最大得分
状态转移方程f[i, j, k, l]可以转移到
f[i + 1, j, k, l] f[i, j + 1, k, l] f[i, j, k + 1, l] f[i, j, k, l + 1]
由于用了一定张数的卡片后的目标格子是确定的,所以每个转移对应加上目标格子的得分的值即可
初值f[0, 0, 0, 0] = 0
ans = f[b[1], b[2], b[3], b[4]],其中b[i]表示移动i格的卡片的个数
时间复杂度O(40^4),空间复杂度O(40^4),可以滚动数组优化一维
另外还有一个时间复杂度O(350*40^3)的方程,这里就不讲了
第三题:二分答案 + 2-SAT
可以证明想到本题是有二分答案的性质的,如果比mid大的边全部一起来都没有出现矛盾,那么比mid 更大的答案肯定可以。
而二分了答案之后,我们就只要判定当前的比mid大的边有没有出现矛盾,即判定由权值比mid大的边构成的子图是不是一个二分图(只有是二分图才能分成两个集合啦),用染色法做这个2-SAT问题,即从任意一个点出发,给它相邻的点染上与这个点不同的颜色,如果染色出现冲突则可以判定为false,没冲突则判定为true
实际复杂度为O(log(maxw)*(n+m))
这只是一个比较直观的解法,其实可以直接排序+并查集判定即可,好像还可以用最大生成树的性质做
第四题:贪心
首先本题容易转化为这样一个模型:将第一行格子当成x点集中的点,将最后一行格子当成y点集中的点,如果在第一行的某个格子建站能覆盖到最后一行的某个格子,则对应点之间连边。然后问题等价于选最少的x点集中的点覆盖所有的y点集中的点。
只有这个裸模型是不够的,直接做难度相当大,所以继续挖掘本题性质。
可以发现每个x点集中的点所能覆盖到的y点集的点会是连续的一段(可由覆盖的过程是一条路径扫过来证明),而且对于x点集中的i和i+1,有i所能覆盖到的右端点小于等于i+1的右端点(这个同样也可以用路径覆盖的过程来证明)
有了这两个结论,贪心的性质就出来了,方法如下:
从左到右枚举y点集的点,如果它还没被覆盖到,则选一个x点集中的最右边的能覆盖到它的点去覆盖它。
预处理出x点集中的所有点所能覆盖的区间左端点右端点,总的复杂度就是O(n^2)的
如果预处理写记忆化搜索,有一个点会爆栈
n=1的情况可以特判