• Codeforces 1335F Robots on a Grid


    Description

    给一个 $n imes m$ 的网格图,每个位置有颜色和方向。颜色为黑 / 白,方向表示这个位置的机器人下一步会往上下左右哪个方向移动一格,问你最多可以放多少个机器人,使得这些机器人行走时永远不会相遇。最大化个数的基础上,最大化黑色格子的机器人个数。

    Solution

    一直无限走下去实在玄学,看看能不能转化一下。

    因为格子有限,所以 无限 $=$ 循环

    换一种方法,我们可以先把每个位置都摆上机器人,一直走起来,删去会重复的。

    显然,每个机器人都是先经过一些奔波,然后在一个环里面一直走下去。

    比如我们现在随便弄来两个机器人,怎么知道它们会不会重复呢?

    首先,假设两个机器人各自奔波时没相遇,也就是到了自己的目标环中,那么它们就永远不会相遇了。这很好理解,如果它们不在一个环中,那显然不可能碰到;如果在一个环中(当然前提是不在一个位置),那么他们之间的距离就永远不会变了,也不会相遇。

    所以,两个机器人相遇的充要条件就是在奔波的路途上相遇,而且之后,该相遇的就一直在一起走了,不该相遇的就永远碰不到了。

    所以,每一条道路的长度肯定不会超过图的总大小(即 $nm$),所以我们只要让每一个位置的机器人都走 $nm$ 步,然后统计位置就行了。

    至于具体怎么统计,可以弄一个 $have_{0/1, ext{pos}}$ 表示最终 $ ext{pos}$ 这个位置有没有黑 / 白色的机器人,然后令 $tot$ 表示总数,$black$ 表示总黑色机器人数,那么就是:

    $$egin{array}{l|l}1 & extbf{for } i gets 1 extbf{ to } nm extbf{ do} \ 2 & qquad extbf{if } have_{0, i} = ext{true} extbf{ then } tot gets tot + 1, black gets black + 1 \ 3 & qquad extbf{else if } have_{1, i} = ext{true} extbf{ then } tot gets tot + 1 \ 4 & qquad extbf{end if} \ 5 & extbf{end for}end{array}$$

    代码仅供参考。

    #include <bits/stdc++.h>
    using namespace std;
    const int NM = 1e6 + 5, LGSZ = 21;
    int n, m, nxt[LGSZ][NM];
    char dir[NM], col[NM], buf[NM];
    bool have[2][NM];
    int main() 
    {
    	int t;
    	scanf("%d", &t);
    	while(t--) 
    	{
    		scanf("%d %d", &n, &m);
    		for(int i = 1; i <= n * m; i++)
    			have[0][i] = have[1][i] = false;
    		for(int i = 1; i <= n; i++) 
    		{
    			scanf("%s", buf + 1);
    			for(int j = 1; j <= m; j++)
    				col[(i - 1) * m + j] = buf[j];
    		}
    		for(int i = 1; i <= n; i++) 
    		{
    			scanf("%s", buf + 1);
    			for(int j = 1; j <= m; j++)
    				dir[(i - 1) * m + j] = buf[j];
    		}
    		for(int i = 1; i <= n * m; i++)
    			switch(dir[i])
    			{
    				case 'U': nxt[0][i] = i - m; break;
    				case 'D': nxt[0][i] = i + m; break;
    				case 'L': nxt[0][i] = i - 1; break;
    				case 'R': nxt[0][i] = i + 1; break;
    			}
    		for(int i = 1; i < LGSZ; i++)
    			for(int j = 1; j <= n * m; j++)
    				nxt[i][j] = nxt[i - 1][nxt[i - 1][j]];
    		for(int i = 1; i <= n * m; i++)
    		{
    			int pos = i;
    			for(int j = LGSZ - 1; ~j; j--)
    				if(n * m >> j & 1) pos = nxt[j][pos];
    			have[col[i] ^ 48][pos] = true;
    		}
    		int black = 0, tot = 0;
    		for(int i = 1; i <= n * m; i++)
    		{
    			if(have[0][i]) tot++, black++;
    			else if(have[1][i]) tot++;
    		}
    		printf("%d %d
    ", tot, black);
    	}
    	return 0;
    }
  • 相关阅读:
    dfs介绍
    UVA11149 矩阵快速幂
    UVA1476 三分法
    漂亮的表达式!(不断补充)
    BC Round#33 B(10的18次方,快速乘法+快速幂取余)
    UVA 1639(组合数学)
    UVA 10612(数论找规律)
    小模板
    1589象棋(大模拟)
    bnuoj 29368 Check the Identity(栈)
  • 原文地址:https://www.cnblogs.com/syksykCCC/p/1335F.html
Copyright © 2020-2023  润新知