hdu5402 Travelling Salesman Problem

本文介绍了一种在特定条件下(至少一个维度为奇数或两个维度均为偶数但不同时为奇数)对棋盘进行遍历的方法。当棋盘的长宽之一为奇数时,所有点都能被覆盖;当长宽均为偶数时,需避开一个特定的奇数点以完成遍历。文章通过实例代码展示了如何寻找这个需要避开的点,并给出了遍历路径的具体构造。

当n,m有一个为奇数时,所有点都可被覆盖。

当n,m全为偶数时,考虑从方格上的点(i,j)走到相邻点,其横纵坐标之和的奇偶性改变一次,因此从偶数点(1,1)走到偶数点(n,m),

经过的偶数点比奇数点多一,由于表格上的奇数点数目和偶数点相同,因此至少有一个奇数点不被遍历,找出并绕过该点即可。

路径经过构造可得。

 

http://acm.hdu.edu.cn/listproblem.php?vol=45

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 1e2 + 10;
 8 const int inf = 0x3f3f3f3f;
 9 
10 int G[maxn][maxn];
11 int n, m, x1, y1, low;
12 int sum;
13 
14 int main(){
15     //freopen("in.txt", "r", stdin);
16     while(~scanf("%d%d", &n, &m)){
17         low = inf;
18         sum = 0;
19         for(int i = 1; i <= n; i++){
20             for(int j = 1; j <= m; j++){
21                 scanf("%d", &G[i][j]);
22                 sum += G[i][j];
23                 if((i + j) % 2 && G[i][j] < low) low = G[i][j], x1 = i, y1 = j;
24             }
25         }
26         if(n % 2){
27             printf("%d\n", sum);
28             for(int i = 1; i < m; i++) putchar('R');
29             for(int i = 0; i < (n - 1) / 2; i++){
30                 putchar('D');
31                 for(int j = 1; j < m; j++) putchar('L');
32                 putchar('D');
33                 for(int j = 1; j < m; j++) putchar('R');
34             }
35             putchar('\n');
36             continue;
37         }
38         if(m % 2){
39             printf("%d\n", sum);
40             for(int i = 1; i < n; i++) putchar('D');
41             for(int i = 0; i < (m - 1) / 2; i++){
42                 putchar('R');
43                 for(int j = 1; j < n; j++) putchar('U');
44                 putchar('R');
45                 for(int j = 1; j < n; j++) putchar('D');
46             }
47             putchar('\n');
48             continue;
49         }
50         printf("%d\n", sum - low);
51         if(y1 % 2){
52             for(int i = 0; i < x1 / 2 - 1; i++){
53                 for(int j = 1; j < m; j++) putchar('R');
54                 putchar('D');
55                 for(int j = 1; j < m; j++) putchar('L');
56                 putchar('D');
57             }
58             for(int i = 0; i < (y1 - 1) / 2; i++) printf("DRUR");
59             printf("RD");
60             for(int i = 0; i < (m - y1 - 1) / 2; i++) printf("RURD");
61             for(int i = 0; i < (n - x1) / 2; i++){
62                 putchar('D');
63                 for(int j = 1; j < m; j++) putchar('L');
64                 putchar('D');
65                 for(int j = 1; j < m; j++) putchar('R');
66             }
67             putchar('\n');
68             continue;
69         }
70         for(int i = 0; i < (x1 - 1) / 2; i++){
71             for(int j = 1; j < m; j++) putchar('R');
72             putchar('D');
73             for(int j = 1; j < m; j++) putchar('L');
74             putchar('D');
75         }
76         printf("DR");
77         for(int i = 0; i < (y1 - 2) / 2; i++) printf("URDR");
78         for(int i = 0; i < (m - y1) / 2; i++) printf("RURD");
79         for(int i = 0; i < (n - x1 - 1) / 2; i++){
80             putchar('D');
81             for(int j = 1; j < m; j++) putchar('L');
82             putchar('D');
83             for(int j = 1; j < m; j++) putchar('R');
84         }
85         putchar('\n');
86     }
87     return 0;
88 }
View Code

 

转载于:https://www.cnblogs.com/astoninfer/p/4800966.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值