Rotation
题意:$N×M$ 的网格图,给定一条网格线连成的闭合路径,计算所有格子转动值的平方和。假设一辆车沿着路径移动,一个人站在某个格子正中间始终对着车,这个人在车开始到停下顺时针转动了 $x$ 度,则他的转动值为 $\frac{x}{360}$ (可以为负数)。
题解:首先,因为起点和终点相同,每个格子的转动值一定为整数。
其次,若路径为简单环,环内的格子转动值均为 $\pm 1$,环外的格子转动值均为 $0$ 。
接着可以发现,每次路径向下时,为左边的格子贡献正的转动值,为右边的格子贡献负的转动值。
用一个看来的巧妙的做法:每次只考虑路径对右侧的格子的影响。上行一次,右侧所有格子加一,下行一次,右侧所有格子减一。这时,这个做法已经不仅限于简单环了。
现在问题转化为给一个矩阵增量,由于只需要最后结果,我们可以利用差分的思想。
在一维时,差分可以将区间增量变成两个点的增量。差分即为前缀和的逆运算,回忆一下二维前缀和的递推:$$sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]$$
设计如下的增量:
进行二维前缀和递推以后即可得到真实的数。
考虑到本题每次更新的矩阵都是直到右边界,所以可以忽略右边的两个增量。
最后,本题需要生成一个长宽不定的矩阵,C++使用 vector 比较方便,C语言查了一下指针和malloc大概要十多行吧。。。
1 | #include <iostream> |
其实我们可以发现,不管考虑哪一侧都可以解决这个问题,当然因为最开始在左上角,维护左侧和上侧可能比较困难。下面放一个维护下侧的:
1 |
|