hdu 5402 Travelling Salesman Problem
-
题意:
给你一个由n*m个格子组成的迷宫,每个格子上有一个非负数,Teacher Mai 每次可以从一个格子走到与它相邻的格子,但每个格子只能走一次, 问从(1, 1)走到(n, m)所经过的格子上的数的最大和是多少, 并输出路径。 -
思路:
(1)首先, 如果n或m是奇数, 那么所有格子都可以到达
(2) 如果n和m都是偶数, 那么按照黑白棋盘染色原理, 假设(1, 1)和(n, m)是黑色, Teacher Mai所走过的黑格数一定比白格数多一, 我们只需在白格子里面找出一个最小的值即可; -
构造路径:
(1) n或m是奇数, 路径很简单, 直接沿(y轴或x轴)走到底再回去即可
(2)n, m都是偶数, 先找到最小值所在的白格子的位置; 假设再(ii, jj)的位置, 先按"R...RDL...LD"的方式走完前2k(2k<ii)行, 然后在ii, ii+1 / ii-1行按'UR', 'DR'这样走, 注意边界条件和(ii, jj)所在的位置即可, 最后再按"DL...LDR...R"走完剩余的部分即可。 -
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 120;
int mp[maxn][maxn];
int main() {
int n, m;
while(~scanf("%d %d", &n, &m)) {
int sum = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
scanf("%d", &mp[i][j]);
sum += mp[i][j];
}
}
if(n & 1 || m & 1) {
printf("%d\n", sum);
if(n & 1) {
for(int k = 1; k <= n; k++) {
for(int i = 1; i < m; i++) {
if(k & 1) printf("R");
else printf("L");
}
if(k != n) printf("D");
}
} else if(m & 1) {
for(int k = 1; k <= m; k++) {
for(int i = 1; i < n; i++) {
if(k & 1) printf("D");
else printf("U");
}
if(k != m) printf("R");
}
}
printf("\n");
continue;
}
//
int mn = 1000000, ii = -1, jj = -1;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(((i + j) & 1) && mn > mp[i][j]) { mn = mp[i][j]; ii = i; jj = j; }
}
}
printf("%d\n", sum - mn);
if(ii == -1 || jj == -1) while(1);
if(ii & 1) {
for(int k = 1; k < ii; k++) {
for(int i = 1; i < m; i++) {
if(k & 1) printf("R");
else printf("L");
}
if(k != n) printf("D");
}
int f = 0; //f=0下 f=1上
for(int i = 0; i < m-1; i++) {
if(i == jj) { printf("R"); continue; }
if(f) printf("UR");
else printf("DR");
f ^= 1;
}
printf("D");
for(int k = ii + 2; k <= n; k++) {
printf("D");
for(int i = 1; i < m; i++) {
if(k & 1) printf("L");
else printf("R");
}
}
} else {
for(int k = 1; k <= ii; k++){
for(int i = 1; i < m; i++) {
if(k & 1) printf("R");
else printf("L");
}
printf("D");
}
int f = 1;
for(int i = 0; i < m-1; i++) {
if(i == jj) { printf("R"); continue; }
if(f) printf("DR");
else printf("UR");
f ^= 1;
}
if(jj + 1 != m) printf("D");
for(int k = ii + 3; k <= n; k++) {
printf("D");
for(int i = 1; i < m; i++) {
if(k & 1) printf("L");
else printf("R");
}
}
}
printf("\n");
}
return 0;
}
/*
测试数据
3 4
1 2 3 4
1 2 3 4
1 2 3 4
4 3
1 2 3
1 2 3
1 2 3
4 4 4
4 4
2 3 3 0
3 3 3 4
3 3 2 1
4 2 3 4
4 4
2 1 3 4
3 3 3 4
3 3 2 1
4 2 3 4
4 4
2 3 3 4
1 3 3 4
3 3 2 1
4 2 3 4
4 4
2 3 3 4
3 3 1 4
3 3 2 1
4 2 3 4
4 4
2 3 3 4
3 3 3 4
3 3 2 1
4 2 0 4
4 4
2 4 3 4
3 3 3 4
3 3 2 1
0 2 3 4
4 4
2 3 3 4
4 3 3 4
3 0 2 1
4 2 3 4
4 4
2 3 3 4
3 3 4 4
3 3 2 1
4 2 3 4
6 4
2 3 3 4
3 3 3 4
3 1 2 4
3 2 3 4
4 4 4 4
4 4 4 4
6 4
2 3 3 4
3 3 3 4
3 3 2 0
2 3 4 4
4 4 4 4
4 4 4 4
6 4
2 3 3 4
3 3 3 4
3 3 2 4
2 3 1 4
4 4 4 4
4 0 4 4
6 4
2 3 3 4
3 3 3 4
3 3 2 4
1 3 4 4
4 4 4 4
4 0 4 4
*/