hdu5402(构造;)

题意:

给出一张图,每个点上都有一个非负的数值;

要求从左上角走到右下角,走过的点不能再走,得到的最大数值是多少,并输出路线;


思路:

首先,如果是奇数行,或者奇数列,就很简单,迂回着走就能全部走完;

现在我们要判断偶数行偶数列的情况;

经过找规律,我们发现,可以在不走某一个点的情况下,完成;也就是我们可以得到所有数值,减掉这个点的数值;

而可以不走的点要满足(i + j)% 2 == 1;

所以我们在所有满足的点里选个最小的减掉;


那么路径该怎么构造;首先在到达我们选的点所在的行之前,还是迂回地遍历;到达那一行之后,开始在两行间上下走;

...*..

......

比如*是我们要删的点,我们就可以DRURDRRURD;绕过那个点,并且到达右下角或左下角,然后继续迂回地遍;


要注意的是选择的点在最后一行的情况,必须提前一行开始;



#include <cstdio> 
#include <cstring>

const int N = 105;
int g[N][N], r, c, x, y;

int main() {
	while (scanf("%d%d", &r, &c) == 2) {
		int sum = 0;
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				scanf("%d", &g[i][j]);
				sum += g[i][j];
			}
		}
		if(r % 2) {
			printf("%d\n", sum);
			for(int i = 1; i <= r; i++) {
				if(i != 1)
					putchar('D');
				for(int j = 1; j < c; j++) {
					if(i % 2)
						putchar('R');
					else
						putchar('L');
				}
			}
			putchar('\n');
			continue;
		}
		if(c % 2) {
			printf("%d\n", sum);
			for(int i = 1; i <= c; i++) {
				if(i != 1)
					putchar('R');
				for(int j = 1; j < r; j++) {
					if(i % 2)
						putchar('D');
					else
						putchar('U');
				}
			}
			putchar('\n');
			continue;
		}
		int MIN = 0x3f3f3f3f;
		for (int i = 0; i < r; i++)	{
			for (int j = 0; j < c; j++) {
				if ((i + j) % 2 && g[i][j] < MIN) {
					MIN = g[i][j];
					x = i;
					y = j;
				}
			}
		}
		printf("%d\n", sum - MIN);
		int k = x;
		if (x == r - 1)
			k = x - 1;
		for (int i = 0; i < k; i++) {
			if (i != 0)
				putchar('D');
			for (int j = 1; j < c; j++) {
				if (i % 2 == 0)	
					putchar('R');
				else
					putchar('L');
			}
		}
		if (k != 0)
			putchar('D');
		int s;
		int cx = k;
		int cy = k % 2 ? c - 1 : 0;
		if (k % 2 == 0) {
			while(1) {
				if (cx == k + 1 && cy == c - 1)
					break;
				if (cx + 1 != x || cy != y) {
					putchar('D');
					cx += 1;
				}else {
					putchar('R');
					cy += 1;
					continue;
				}
				if (cx == k + 1 && cy == c - 1)
					break;
				putchar('R');
				cy += 1;
				if (cx == k + 1 && cy == c - 1)
					break;
				if (cx - 1 != x || cy != y) {
					putchar('U');
					putchar('R');
					cx -= 1;
					cy += 1;
				}else {
					putchar('R');
					cy += 1;
					if (cx == k + 1 && cy == c - 1)
						break;
					putchar('U');
					putchar('R');
					cx -= 1;
					cy += 1;
					continue;
				}
			}
		}
		if (k % 2) {
			while(1) {
				if (cx == k + 1 && cy ==0)
					break;
				if (cx + 1 != x || cy != y) {
					putchar('D');
					cx += 1;
				}else {
					putchar('L');
					cy -= 1;
					continue;
				}
				if (cx == k + 1 && cy == 0)
					break;
				putchar('L');
				cy -= 1;
				if (cx == k + 1 && cy == 0)
					break;
				if (cx - 1 != x || cy != y) {
					putchar('U');
					putchar('L');
					cx -= 1;
					cy -= 1;
				}else {
					putchar('L');
					cy -= 1;
					if (cx == k + 1 && cy == 0)
						break;
					putchar('U');
					putchar('L');
					cx -= 1;
					cy -= 1;
					continue;
				}
			}
		}
		if (cx != r- 1 || cy != y) {
			cx += 1;
			for (int i = cx; i < r; i++) {
				putchar('D');
				for (int j = 1; j < c; j++) {
					if (i % 2)	
						putchar('R');
					else
						putchar('L');
				}
			}
		}
		putchar('\n');
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值