博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 5402 模拟 构造 Travelling Salesman Problem
阅读量:5082 次
发布时间:2019-06-13

本文共 4073 字,大约阅读时间需要 13 分钟。

题意:

有一个n * m的数字矩阵,每个格子放着一个非负整数,从左上角走到右下角,每个格子最多走一次,问所经过的格子的最大权值之和是多少,并且输出一个路径。

分析:

如果n和m有一个是偶数的话,那么只要按照蛇形的走法一直走下去即可。

比如n为奇数的时候就这样,左右左右地蛇形走。

同样的,如果m为奇数的时候,也可以上下上下地蛇形走。

 

但如果n和m都为偶数的时候,就会无法走完全部的格子,最终到达右下角。

但是可以少走一个格子,而且这个格子必须是那种行标加列标为奇数的格子才行(行和列从1开始),所以我们就绕过权值最小的符合条件的格子,走其他所有的格子获得最大值。

 

比如像这种:

除了那个选出来的格子不走,其余的格子可以全部走到。

所以就直接这样构造出一条路径出来。

我们可以这样构造,假设选出来的不走的格子为(x, y),把这个地图分成三部分:选第x行和相邻的一行,这两个作为一个「长城」的走法。

然后「长城」上面和下面用蛇字形走法,最后走到右下角。

 

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 7 const int maxn = 500 + 10; 8 9 int n, m, sum, _min; 10 int a[maxn][maxn]; 11 12 int r, c; 13 14 bool vis[maxn][maxn]; 15 16 void snake(int n, int m, char d, char revd, char nxt) 17 { 18 for(int i = 1; i <= n; i++) 19 { 20 if(i & 1) 21 { 22 for(int j = 1; j < m; j++) printf("%c", d); 23 if(i < n) printf("%c", nxt); 24 } 25 else 26 { 27 for(int j = 1; j < m; j++) printf("%c", revd); 28 if(i < n) printf("%c", nxt); 29 } 30 } 31 } 32 33 int main() 34 { 35 while(scanf("%d%d", &n, &m) == 2 && n) 36 { 37 sum = 0; 38 _min = 100000000; 39 for(int i = 1; i <= n; i++) 40 for(int j = 1; j <= m; j++) 41 { 42 scanf("%d", &a[i][j]); 43 sum += a[i][j]; 44 if(((i + j) & 1) && a[i][j] < _min) { _min = a[i][j]; r = i; c = j; } 45 } 46 47 if(n & 1) 48 { 49 printf("%d\n", sum); 50 snake(n, m, 'R', 'L', 'D'); 51 puts(""); 52 continue; 53 } 54 55 if(m & 1) 56 { 57 printf("%d\n", sum); 58 snake(m, n, 'D', 'U', 'R'); 59 puts(""); 60 continue; 61 } 62 63 printf("%d\n", sum - _min); 64 65 if(r - 2 > 0) snake(r - 2, m, 'R', 'L', 'D'); 66 if(r - 1 > 1) printf("D"); 67 68 int x, y, up, down; 69 if(r <= 2) 70 { 71 x = y = 1; 72 up = 1, down = 2; 73 } 74 else 75 { 76 up = r - 1, down = r; 77 x = r - 1; 78 if(r & 1) y = m; else y = 1; 79 } 80 81 memset(vis, false, sizeof(vis)); 82 for(int i = 0; i <= n + 1; i++) vis[i][0] = vis[i][m + 1] = true; 83 for(int i = 0; i <= m + 1; i++) vis[0][i] = vis[n + 1][i] = true; 84 vis[x][y] = true; 85 vis[r][c] = true; 86 if(y == 1) 87 { 88 for(int i = 1; i <= m * 2 - 2; i++) 89 { 90 if(x == down) 91 { 92 if(!vis[x-1][y]) { x--; vis[x][y] = true; printf("U"); } 93 else { y++; vis[x][y] = true; printf("R"); } 94 } 95 else 96 { 97 if(!vis[x+1][y]) { x++; vis[x][y] = true; printf("D"); } 98 else { y++; vis[x][y] = true; printf("R"); } 99 }100 }101 }102 else103 {104 for(int i = 1; i <= m * 2 - 2; i++)105 {106 if(x == down)107 {108 if(!vis[x-1][y]) { x--; vis[x][y] = true; printf("U"); }109 else { y--; vis[x][y] = true; printf("L"); }110 }111 else112 {113 if(!vis[x+1][y]) { x++; vis[x][y] = true; printf("D"); }114 else { y--; vis[x][y] = true; printf("L"); }115 }116 }117 }118 119 if(down + 1 <= n)120 {121 printf("D");122 if(y == 1) snake(n - down, m, 'R', 'L', 'D');123 else snake(n - down, m, 'L', 'R', 'D');124 }125 126 puts("");127 }128 129 return 0;130 }
代码君

 

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4743293.html

你可能感兴趣的文章
jQuery轮 播的封装
查看>>
一天一道算法题--5.30---递归
查看>>
JS取得绝对路径
查看>>
排球积分程序(三)——模型类的设计
查看>>
python numpy sum函数用法
查看>>
php变量什么情况下加大括号{}
查看>>
linux程序设计---序
查看>>
【字符串入门专题1】hdu3613 【一个悲伤的exkmp】
查看>>
C# Linq获取两个List或数组的差集交集
查看>>
HDU 4635 Strongly connected
查看>>
ASP.NET/C#获取文章中图片的地址
查看>>
Spring MVC 入门(二)
查看>>
格式化输出数字和时间
查看>>
页面中公用的全选按钮,单选按钮组件的编写
查看>>
java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
查看>>
BZOJ 1047 HAOI2007 理想的正方形 单调队列
查看>>
各种语言推断是否是手机设备
查看>>
这个看起来有点简单!--------实验吧
查看>>
PHP count down
查看>>
JVM参数调优:Eclipse启动实践
查看>>