グリッド上のCodeforces 1335Fロボット

説明文

$ n \ x m $のグリッドグラフに、各場所の色と方向を指定します。色は黒/白で、方向はこの位置のロボットが1グリッド上で上下左右に移動する方向を示し、歩行中にこれらのロボットが出会うことがないように、最大​​で何台のロボットを配置できるかを尋ねます。数を最大化することに基づいて、黒いグリッドロボットの数を最大化します。

解決

無期限に続けて、それが変形できるかどうかを見るのは本当に形而上学的です。

限られたグリッドの、そのため、無制限$ = $循環

別の言い方をすると、ロボットの各位置を最初に配置し、歩き続けると、削除が繰り返されます。

明らかに、各ロボットは最初にいくつかのランニングを通過し、次にリングを歩きます。

たとえば、2つのロボットがある場合、それらが繰り返されるかどうかをどのようにして知ることができますか?

まず、2つのロボットが走り回ったときにお互いに会わなかった、つまり、2つのロボットが自分のターゲットリングに到達したとすると、2人のロボットは決して会わないと仮定します。これは簡単に理解できます。彼らが輪の中にない場合、明らかに遭遇することは不可能です。彼らが輪の中にいる場合(もちろん、それらが位置にない場合)、それらの間の距離は決して変化せず、出会うこともありません。 。

したがって、2つのロボットが出会うための必要十分条件は、路上で出会うことであり、その後は出会った人が一緒に歩いているはずであり、出会ったはずのない人が触れられることはありません。

したがって、各道路の長さはマップの合計サイズ(つまり$ nm $)を超えないようにする必要があるため、各位置のロボットに$ nm $のステップを実行させ、位置を計算するだけで済みます。

特定の統計については、$ have_ {0/1、\ text {pos}} $を取得して、最後の$ \ text {pos} $がこの場所に黒/白のロボットであることを示し、$ tot $で合計を表すことができます。黒の$は黒のロボットの総数を表し、次のようになります。

$$ \ begin {array} {l | l} 1&\ textbf {for} i \ gets 1 \ textbf {to} nm \ textbf {do} \\ 2&\ qquad \ textbf {if} have_ {0、i } = \ text {true} \ textbf {then} tot \ gets tot + 1、black \ gets black + 1 \\ 3&\ qquad \ textbf {else if} have_ {1、i} = \ text {true} \ textbf {then} tot \ gets tot + 1 \\ 4&\ qquad \ textbf {end if} \\ 5&\ textbf {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 i = 1; i <= n * m; i ++)
			switch(dir [i])
			{ 
				case 'U':nxt [0] [i] = i-m; ブレーク; 
				ケース 'D':nxt [0] [i] = i + m; ブレーク; 
				ケース 'L':nxt [0] [i] = i-1; ブレーク; 
				ケース 'R':nxt [0] [i] = i + 1; ブレーク; 
			} 
		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 \ n"、tot、black); 
	} 
	0を返します。
}

おすすめ

転載: www.cnblogs.com/syksykCCC/p/1335F.html