CF1817D Toy Machine

注意,這個做法幾乎沒有用到任何歸納,以及任何套路的構造方法。也沒有用到可能有用的置換羣的構造,屬於瞪眼瞪出來的。所以可擴展性極差。

一個很自然的想法是我們需要用到一些 LRDU 的“組合技”來讓第 \(k\) 塊更加靠近答案。

第一步觀察,當我們的塊是最中間的時候,只需要一步 DL 即可。但似乎沒什麼用。

仔細思考一下,我們想把一個塊不斷地往前挪,等價於把它前面的一個數挪到後面去。那麼很自然的想法是把數卡到第一個黑格子上面,然後不讓它往下走,再把它放到右邊去,也就是 LDRU

你驚喜的試了幾次,發現好像不斷執行 LDRU 就好了,可是當你試到後面時候發現不太行,原因是卡到了中間黑方格或後面下不來了。

現在我們還是需要往前挪,在通過一些手玩之後,還有一步比較有用的組合:LDLU。這可以把一些數卡到左邊下面,這樣再執行一遍 DRUR 就可以把原先的數放到等價於中間位置的那個地方了。

你又試了幾次,發現太靠後的地方還是不太行,原因是會在 U 的那一步被卡住。換一種思路,把需要搞得數放到最右邊,其他數卡到下邊。

執行若干次 LDLU 直到它到了中間,然受執行 LDRD,把所求卡到右邊下面,然後不斷執行 ULDL,這樣把左邊上面也卡滿。發現這樣最後一個一定是所求的放個,最後再執行一遍 RDL

分析一下,一開始會做 \(\frac{n}{2}\)LDLU,然後會做 \(\frac{n}{2}\)ULDL,於是總次數是 \(4n+O(1)\) 的。

我以爲我的做法很菜,但是標算好像也是 \(4n+O(1)\) 步,那沒事了。

#include <bits/stdc++.h>
using namespace std;
int n, k;
int main()
{
	cin >> n >> k;
	if (k <= n / 2)
	{
		for (int i = 1; i < k; i++) printf("LDRU");
		printf("L");
	}
	else if (k <= n / 2 + (n / 2) / 2)
	{
		for (int i = 1; i < k - n / 2; i++) printf("LDLU");
		printf("DRUR");
		for (int i = 1; i < n / 2; i++) printf("LDRU");
		printf("L");
	}
	else
	{
		for (int i = 1; i < k - n / 2; i++) printf("LDLU");
		printf("LDRD");
		for (int i = 1; i < n / 2; i++) printf("ULDL");
		puts("RDL");
		
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章