您的位置:首页 > 大数据 > 人工智能

HDU 5402 Travelling Salesman Problem (2015 Multi-University Training Contest 9 2015多校联合)

2015-08-19 09:23 483 查看
题目传送门:HDU5402 Travelling Salesman Problem


Travelling Salesman Problem

Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 522 Accepted Submission(s): 181

Special Judge


Problem Description

Teacher Mai is in a maze with n rows
and m columns.
There is a non-negative number in each cell. Teacher Mai wants to walk from the top left corner (1,1) to
the bottom right corner (n,m).
He can choose one direction and walk to this adjacent cell. However, he can't go out of the maze, and he can't visit a cell more than once.

Teacher Mai wants to maximize the sum of numbers in his path. And you need to print this path.

Input

There are multiple test cases.

For each test case, the first line contains two numbers n,m(1≤n,m≤100,n∗m≥2).

In following n lines,
each line contains m numbers.
The j-th
number in the i-th
line means the number in the cell (i,j).
Every number in the cell is not more than 104.

Output

For each test case, in the first line, you should print the maximum sum.

In the next line you should print a string consisting of "L","R","U" and "D", which represents the path you find. If you are in the cell (x,y),
"L" means you walk to cell (x,y−1),
"R" means you walk to cell (x,y+1),
"U" means you walk to cell (x−1,y),
"D" means you walk to cell (x+1,y).

Sample Input

3 3
2 3 3
3 3 3
3 3 2


Sample Output

25
RRDLLDRR


Author

xudyh

Source

2015 Multi-University Training Contest 9

因为在队里我比较擅长DFS BFS走迷宫这样的题,所以看到这题果断自己接手了。读题发现并不是走迷宫啊- -和DFS BFS也没什么关系啊!就是从左上角走到右下角,尽可能使走过的路加起来的数字和最大。类似吃豆子,我们要想玩贪吃蛇那样 争取把格子里面的东西都吃了。那么由此我就得出了4种情况,行列分别为奇数奇数、奇数偶数、偶数奇数、偶数偶数。在纸上画一画,发现其实分为3种情况,上图!(诅咒吐槽我画的图的人找不到对象→_→)


可以发现:行列分别为奇数奇数、奇数偶数的是一类,对应图1、2,可以用RRRDLLLDRRR这样的方式实现。 第二类是行列为偶数奇数,对应图3,可以用DDDDRLLLLRDDD的方式实现。可以发现,只要行列不全为偶数,那么我们就可以走完整个图,输出的数字也就是整个格子所有数字之和。第三类对应图4,也就是行列都为偶数。这样的话我们发现,格子并不能全走完。接下来我们就要讨论了。

画一个4x4的格子,我们可以发现,在这种情况里,总是要有一个格子走不到,要被抛弃。那么我们画一画,到底哪些点是可以被抛弃的。画了之后发现,奇数行的第偶数个格子和偶数行的第奇数个格子都是可以被抛弃的。如果不好理解的话,我们把格子看错黑白棋的棋盘,如果左上角为黑色的话,那么所有白色格子都是可以被抛弃的那一个格子的位置。为了加和最大,我们只需要找这些白色格子里面数字最小的那个,用x y记录它的位置。那么我们要输出的sum和就是sum-min,(或者说sum-a[x][y])

接下来就是走法了,方法是这样:在走到最小值格子所在行或者上一行之前,我们采用图1、2的走法,也就是RRRDLLLDRRRDLLLD,走到格子所在的行或者前一行时,我们采用图3走法,来搞定这两行,即RDRURDRU,如果走到最小值格子所在的点,我们只需绕过它即可,比如URDRRURDR。喏,只需要在走到格子那里是不再U或者D经过它,而是改成R,绕过它。看图:



到这里就解决啦。附上出题人解题报告:



下面附上AC代码:

#include <cstdio>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <cstring>
using namespace std;
#define TEST cout<<"wwwwwwwwww"<<endl
int maze[105][105];
int main()
{
int n,m,sum;
int min;
int i,j;
int x,y;
while(scanf("%d%d",&n,&m)!=EOF)
{
min=0x7f7f7f7f;
sum=0;
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
scanf("%d",&maze[i][j]);
sum+=maze[i][j];
if(m%2==0 && n%2==0)
{
if(i%2==0 && j%2!=0)
{
if(maze[i][j]<min)
{
min=maze[i][j];
x=i;
y=j;
}
}

if(i%2!=0 && j%2==0)
{
if(maze[i][j]<min)
{
min=maze[i][j];
x=i;
y=j;
}
}
}
}
}

if(n%2!=0)
{
printf("%d\n",sum);
for(i=1;i<=n;i++)
{
if(i%2!=0)
{
for(j=1;j<=m-1;j++)
printf("R");
}
if(i%2==0)
{
for(j=1;j<=m-1;j++)
printf("L");
}
if(i==n && j==m)
break;
else
printf("D");
}
}
else if(m%2!=0)
{
printf("%d\n",sum);
for(i=1;i<=m;i++)
{
if(i%2!=0)
{
for(j=1;j<=n-1;j++)
printf("D");
}
if(i%2==0)
{
for(j=1;j<=n-1;j++)
printf("U");
}
if(i==m && j==n)
break;
else
printf("R");
}
}
else
{
printf("%d\n",sum-min);
for(i=1;i<=n;i+=2)
{
if(x==i || x==i+1)
{
for(j=1;j<y;j++)
{
if(j%2!=0)
printf("D");
else
printf("U");
printf("R");
}
if(y<m)
printf("R");
for(j=y+1;j<=m;j++)
{
if(j%2!=0)
printf("U");
else
printf("D");
if(j<m)
printf("R");
}
if(i<n-1)
printf("D");
}
else if(x<i)
{
for(j=1;j<m;j++)
printf("L");
printf("D");
for(j=1;j<m;j++)
printf("R");
if(i<n-1)
printf("D");
}
else
{
for(j=1;j<m;j++)
printf("R");
printf("D");
for(j=1;j<m;j++)
printf("L");
printf("D");
}
}
}
printf("\n");
}
return 0;
}
重要的话说三遍:不要吐槽我的图!不要吐槽我的图!不要吐槽我的图! QQ截图截了个白色地方鼠标画的!!!!!鼠绘啊有木有!!!!这行字加特技!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: