最近在做TopCoder模拟赛……就是找原来的SRM按照TC的规则去做……
SRM470
250pts:一排房间标号为0~N。A和B分别在0和N号房间。相邻房间有门隔开,每扇门都有一个1~16的颜色。双方轮流选一种颜色然后打开所有选定颜色的门,A先手。有一个房间是目标房间,先到者胜,如果同时到达则平。问双方在必胜策略下A是否能赢,以及最少操作次数。
分析:比较直观的做法就是状压DP,用一个二进制数表示哪些颜色已经被选了,先处理出所有必胜、必败和平手态,然后转移。但事实上是可以贪心的。如果A要获胜那么就要把0~目标之间的门全部打开,令这些门的颜色构成的集合为S,那么A肯定只会选S中的元素;类似的B也会选择自己的集合T。同时为了放置对方获胜,A会尽量选S and !T中的元素,B会尽量选T and !S中的元素。按这个策略贪心即可。
500pts:有两排点,每排N个,从左到右编为1~N。要在上下的点之间连线,每个点只能与一个点连线。现在给定已经连好了的K条线,求期望的线段交点数。
分析:构造数列A,对于上排点x连向下排点y的线段,令A[x]=y,不难发现所求即数列的期望逆序对数。假设K=0,那么期望为N(N-1)/4(共N(N-1)/2对数对,每对顺序相反的概率为0.5)。那么将期望的贡献分为三部分:
1、确定的K个数之间构成的逆序对。这部分贡献在任何情况下都是存在的;
2、未确定的(N-K)个数之间构成的逆序对。可以用上面的公式直接计算;
2、确定的与未确定的数之间构成的逆序对。枚举每个已确定的数x,考虑每个未确定的数y。如果y>x,只有y在x前面才会产生贡献;y<x同理。y在x的方案数为x前面空位数*(N-K-1)!,贡献即空位数/(N-K)。统计大于和小于每个已确定数的未确定数个数,然后求和即可。
总期望即上述三项之和。
1000pts:在N*N的网格图上有至多4对城市,以及一些障碍。每类障碍四连通,摧毁需要固定代价。现在要连接每对城市,路径上的障碍都要被摧毁,求最小代价。
分析:如果只有一对城市那么答案就是最短路。多对城市与一对城市的不同就在于多条路径可以合并,合并的路径上代价只算一次。那么考虑DP,用f[i][j]表示代价,其中i为一个节点,j为一个二进制数,表示这些点发出的路径已经合并。每次从相邻节点转移,考虑是在当前节点合并还是已经在之前就完成了合并。
事实上这个问题所求的是一个最小代价斯坦纳树森林。状态压缩也可以理解为将哪几对点划到一棵树。
SRM441:
250pts:定义一个排列A的子排列B为:B[0]=0, B[i]=A[B[i - 1]]。如果一个排列的子排列也是一个排列,则称该排列为完美排列。给定排列P,求至少需要修改P的几位,使得P成为完美排列。
分析:如果把A看做一个置换,不难发现B中的元素实际上就是A中元素0所在的循环中的元素。一个排列为完美排列也即该置换只有一个循环。那么需要修改的位数也即置换中循环的个数。注意特判只有一个循环的情况。
500pts:给定一个无向图G,现在定义一种变换操作:选择四个点A、B、C和D,其中A与B、C与D有连边,其他点对之间没有连边。删去A-B、C-D,连上A-C、B-D,或者连上A-D、B-C。问能否通过这种操作使得G成为连通图,并求出最小操作次数。
分析:我们考虑什么时候可以进行操作。可以发现,如果一个连通块的边数≥点数(即不是一棵树),那么它可以和另一个连通块进行操作,操作完成之后两个连通块合为一个连通块。那么可以构造如下算法:首先找出所有连通块,求出其点数和边数。如果存在边数=点数-1的连通块,就向其他连通块合并。一直合并直到没有边数=点数-1的连通块,或者仍然有这种连通块但是无法再合并(即无解)。记已进行的操作数为x,那么答案即x+剩余连通块数-1。注意特判图中存在孤立点的情况(无解)。
1000pts:有一张被划分成H*W块的白纸,进行K次操作。每次沿着一条竖直的网格线折叠,然后再水平地折叠成均等的c份(折c-1次)。此时选择一个矩形区域染色,颜料会透过标程渗透到折叠的每一层。染色之后展开。如此进行K次操作,每次操作折叠的网格线、c值和染色区域都可能不同。求所有操作完成后还有几个格子没有染色。c≤1000、K≤50,H、W很大。
分析:每次染色最多新增2000个矩形,那么一共最多有10w个。用线段树做矩形面积并即可。