P6550题解

P6550 [COCI2010-2011#2] LUNAPARK

题目传送门

题解

论证简单,构造逆天(好吧其实就是烦了点)。

每个格子是正整数,所以我们必然尝试多走格子。我们发现,只要 \(r,c\) 中有一个是奇数,我们就可以全部走到,构造很简单:我们找准奇数边,假设是 \(r\),蛇形地走,显然在奇数行我们会结束在末尾,在偶数行我们会结束在开头,所以是可行的。

if(r%2==1) {
    for(int i=1;i<=r;i++) {
        for(int j=1;j<c;j++)
            if(i%2==1) putchar('R');
            else putchar('L');	
        if(i!=r) putchar('D');
    }
    return 0;
}
if(c%2==1) {
    for(int i=1;i<=c;i++) {
        for(int j=1;j<r;j++)
            if(i%2==1) putchar('D');
            else putchar('U');	
        if(i!=c) putchar('R');
    }
    return 0;
}

我们现在只要考虑 \(r,c\) 均为偶数。

首先证明:此时不能走完。黑白染色易证(可以看其他题解)。

顺带的,我们可以证明:至少要抛弃一个白格才能走到终点(设起点是黑格)。

至于抛弃的白格有什么限制吗?答案是没有。

构造如下(以下建议画图理解):

我们每两行一考虑。

\(1\) 这两行没有出现要抛弃的点,且该点在这两行下面:按 \(RRR\cdots RDLLL\cdots LD\) 走。

\(2\) 这两行没有出现要抛弃的点,且该点在这两行上面:按 \(LLL\cdots LDRRR\cdots LR\) 走。

\(3\) 这两行出现了要抛弃的点:

再分类,我们每两列一考虑。

\((1)\) 这两列没有出现要抛弃的点,且该点在这两列右面:按 \(DRUR\) 走。

\((2)\) 这两行没有出现要抛弃的点,且该点在这两列左面:按 \(URDR\) 走。

\((3)\) 这两列出现了要抛弃的点:

分奇偶行考虑:

  • 在奇数行:按 \(DRR\) 走。

  • 在偶数行:按 \(RDR\) 走。

就构造完成了。

结束了吗?还有一个恶心的东西叫边界,一定不要走出去了!

完整代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd() {
	int s=0,m=0;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
	while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return m?-s:s;
}
int r,c,a[1005][1005];
int minn=LLONG_MAX,minx,miny;
signed main() {
	cin>>r>>c;
	for(int i=1;i<=r;i++)
		for(int j=1;j<=c;j++)
			a[i][j]=rd();
	if(r%2==1) {
		for(int i=1;i<=r;i++) {
			for(int j=1;j<c;j++)
				if(i%2==1) putchar('R');
				else putchar('L');	
			if(i!=r) putchar('D');
		}
		return 0;
	}
	if(c%2==1) {
		for(int i=1;i<=c;i++) {
			for(int j=1;j<r;j++)
				if(i%2==1) putchar('D');
				else putchar('U');	
			if(i!=c) putchar('R');
		}
		return 0;
	}
	for(int i=1;i<=r;i++)
		for(int j=1;j<=c;j++)
			if((i+j)%2==1&&a[i][j]<minn)
				minn=a[i][j],minx=i,miny=j;
	for(int i=1;i<=r;i+=2) {
		if(i+1<minx) {
			for(int j=1;j<c;j++)
				putchar('R');
			putchar('D');
			for(int j=1;j<c;j++)
				putchar('L');
			if(i+1!=r) putchar('D');
		}
		else if(i>minx) {
			for(int j=1;j<c;j++)
				putchar('L');
			putchar('D');
			for(int j=1;j<c;j++)
				putchar('R');
			if(i+1!=r) putchar('D');
		}
		else {
			for(int j=1;j<=c;j+=2) {
				if(j+1<miny) {
					putchar('D');
					putchar('R');
					putchar('U');
					if(j+1!=c) putchar('R');
				}
				else if(j>miny) {
					putchar('U');
					putchar('R');
					putchar('D');
					if(j+1!=c) putchar('R');
				}
				else {
					if(minx%2==1) {
						putchar('D');
						putchar('R');
						if(j+1!=c) putchar('R');
					}
					else {
						putchar('R');
						putchar('D');
						if(j+1!=c) putchar('R');
					}
				}
			}
			if(i+1!=r) putchar('D');
		}
	}
	return 0;
}

posted @ 2024-01-19 15:30  operator-  阅读(32)  评论(0)    收藏  举报