HDU 5402 Travelling Salesman Problem (模拟 有规律)

Travelling Salesman Problem

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

Total Submission(s): 568    Accepted Submission(s): 200

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

题目大意:给出一个n*m的棋盘,每一个小方格内有一个数值,问从左上角走到右下角,经过的方格的数值和最大是多少。(每个方格只能走一次)

解题思路:

首先如果n为奇数或者m为奇数,那么显然可以遍历整个棋盘。

如果n,m都为偶数,那么将棋盘黑白染色,假设(1,1)和(n,m)都染为黑色,其他的与黑色相邻的方格染成白色,与白色方格相邻的染成黑色,那么这条路径中黑格个数比白格个数多1个,而棋盘中黑白格子个数相同,所以必然有一个白格不会被经过,所以选择白格中权值最小的不经过。

构造方法是这样,首先RRRRDLLLLD这样的路径走到这个格子所在行或者上一行,然后DRUR这样走到这个格子的所在列或者前一列,然后绕过这个格子。然后走完这两行,接着按LLLLDRRRR这样的路径往下走。

如上面所说;

当n或m为奇数时,棋盘的所有点都可以遍历。

当n和m都是偶数时(如上图),按照黑白涂色的方式,可以发现无论如何选择路径,走过的黑块数都比红块数多一个,最佳路径则是只有一个红块未走,选择红块值最小的即可。

如果n*m的棋盘是按照1到n和1到m,那么红块所在的位置[i][j]是(i+j)是奇数(即i和j一个是奇数一个是偶数)。假设未走的位置是(x,y)

对于路径的输出可以分为两类,

第一类:x是偶数(y一定是奇数)     如下图:

从第1行到底x-2行,如果是奇数行,一直R,最后一个D;如果是偶数行,一直L,最后一个D。

第x-1和第x行,如果是第y列,R;如果是奇数列,DR;如果是偶数列,UR,无论是奇数列还是偶数列最后一列都没有R。如果x等于n,到这里就结束了;如果x不等于n,D。

从第x+1行到第n行,如果是奇数行,一直L,最后一个D;如果是偶数行,一直R,最后一个D,无论是奇数行还是偶数行最后一行没有D。

第二类:y是偶数(x一定是奇数)    如下图

从第1列到底y-2行,如果是奇数列,一直D,最后一个R;如果是偶数列,一直U,最后一个R。

第y - 1和第y列,如果是第x行,R;如果是奇数行,RD;如果是偶数行,LD,无论是奇数行还是偶数行最后一行都没有D。如果y等于m,到这里就结束了;如果y不等于m,R。

从第y + 1行到第m列,如果是奇数列,一直U,最后一个R;如果是偶数列,一直D,最后一个R,无论是奇数列还是偶数列最后一列没有R。

代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-6)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define mod 1e9+7
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;

int main()
{
    int i,j,k,x,y,n,m,ans,minx,a[120][120];
    //freopen("dd4.txt","w",stdout);
    while(~scanf("%d%d",&n,&m))
    {
        ans=0;
        minx=9999999;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
                ans+=a[i][j];
                if((i+j)&1)
                {
                    if(a[i][j]<minx)
                    {
                        minx=a[i][j];
                        x=i;
                        y=j;
                    }

                }
            }
        }
        if(n&1)
        {
            printf("%d\n",ans);
            for(i=1;i<=n;i++)
            {
                if(i&1)
                {
                    for(j=1;j<m;j++)
                        printf("R");
                }
                else
                {
                    for(j=1;j<m;j++)
                        printf("L");
                }
                if(i!=n)
                    printf("D");
            }
            printf("\n");
        }
        else if(m&1)
        {
            printf("%d\n",ans);
            for(i=1;i<=m;i++)
            {
                if(i&1)
                {
                    for(j=1;j<n;j++)
                        printf("D");
                }
                else
                {
                    for(j=1;j<n;j++)
                        printf("U");
                }
                if(i!=m)
                    printf("R");
            }
            printf("\n");
        }
        else
        {
            printf("%d\n",ans-minx);
            //printf("x=%d y=%d\n",x,y);
            if(n==2&&m==2)
            {
                if(minx==a[1][2])
                    printf("DR\n");
                else
                    printf("RD\n");
            }
            else
            {
                if(x%2==0)
                {
                    for(i=1;i<x-1;i++)
                    {
                        for(j=1;j<m;j++)
                        {
                            if(i&1)
                                printf("R");//->
                            else
                                printf("L");//<-
                        }
                        printf("D");//V
                    }
                    for(j=1;j<=m;j++)
                    {
                        if(j<y)
                        {
                            if(j&1)
                                printf("D");
                            else
                                printf("U");
                        }
                        else if(j>y)
                        {
                            if(j&1)
                                printf("U");
                            else
                                printf("D");
                        }
                        if(j!=m)
                            printf("R");
                    }
                    if(x!=n)
                        printf("D");
                    for(i=x+1;i<=n;i++)
                    {
                        for(j=1;j<m;j++)
                        {
                            if(i&1)
                                printf("L");
                            else
                                printf("R");
                        }
                        if(i!=n)
                            printf("D");//V
                    }
                    printf("\n");
                }
                else if(y%2==0)
                {
                    for(i=1;i<y-1;i++)
                    {
                        for(j=1;j<n;j++)
                        {
                            if(i&1)
                                printf("D");
                            else
                                printf("U");
                        }
                        printf("R");
                    }
                    for(i=1;i<=n;i++)
                    {
                        if(i<x)
                        {
                            if(i&1)
                                printf("R");
                            else
                                printf("L");
                        }
                        else if(i>x)
                        {
                            if(i&1)
                                printf("L");
                            else
                                printf("R");
                        }
                        if(i!=n)
                            printf("D");
                    }
                    if(y!=m)
                        printf("R");
                    for(i=y+1;i<=m;i++)
                    {
                        for(j=1;j<n;j++)
                        {
                            if(i&1)
                                printf("U");
                            else
                                printf("D");
                        }
                        if(i!=m)
                            printf("R");
                    }
                    printf("\n");
                }
            }
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-31 16:37:12

HDU 5402 Travelling Salesman Problem (模拟 有规律)的相关文章

构造 - HDU 5402 Travelling Salesman Problem

Travelling Salesman Problem Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5402 Mean: 现有一个n*m的迷宫,每一个格子都有一个非负整数,从迷宫的左上角(1,1)到迷宫的右下角(n,m),并且使得他走过的路径的整数之和最大,问最大和为多少以及他走的路径. analyse: 首先,因为每个格子都是非负整数,而且规定每个格子只能走一次,所以为了使和尽可能大,必定是走的格子数越多越好.这样我们就需

HDOJ 5402 Travelling Salesman Problem 模拟

行数或列数为奇数就能够所有走完. 行数和列数都是偶数,能够选择空出一个(x+y)为奇数的点. 假设要空出一个(x+y)为偶数的点,则必须空出其它(x+y)为奇数的点 Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 747    Accepted Submission(s): 272

HDU 5402 Travelling Salesman Problem (构造)(好题)

大致题意:n*m的非负数矩阵,从(1,1) 只能向四面走,一直走到(n,m)为终点,路径的权就是数的和,输出一条权值最大的路径方案 思路:由于这是非负数,要是有负数就是神题了,要是n,m中有一个是奇数,显然可以遍历,要是有一个偶数,可以画图发现,把图染成二分图后,(1,1)为黑色,总能有一种构造方式可以只绕过任何一个白色的点,然后再遍历其他点,而绕过黑色的点必然还要绕过两个白色点才能遍历全部点,这是画图发现的,所以找一个权值最小的白色点绕过就可以了, 题解给出了证明: 如果n,mn,m都为偶数,

HDU 5402 Travelling Salesman Problem (MUT#9 暴力模拟)

[题目链接]click here~~ [题目大意]:走方格,从[1,1]到[n,m],求中间过程得到的数字和最大,并且输出路径 [思路]: 如果n和m里面有一个是奇数那么全部走遍就好了. 否则要找一个最小的点不要,这个点的坐标要满足x+y是奇数 如果不是的话,舍弃该点一定会导致另外一个点也走不到. 然后找到这个点,暴力输出路径即可. 代码: #include <bits/stdc++.h> using namespace std; const int N=105; typedef long l

hdu(5402)——Travelling Salesman Problem(模拟题)

啊...这道题我一开始的想法是dp,因为我们要求的是在这个区间中和的最大值. 但是没想到只要暴力就好了. 这道题用到了一个著名的想法是:黑白棋盘染色问题. 题意: 现在给你一个n*m的矩阵,然后告诉你每个矩阵中的数字,然后现在要从左上角走到右下角,然后问你所能获得的数字和的最大值是多少.当然,你只能往四个方向走,而且每个点只能走一次.并且叫你输出路径. 思路: 这里我分了三种情况. 1)首先当行或者列数都是1的时候,那么我们就只可能有一种走法(横着走或者是竖着走)然后获取所有的数值. 2)当行数

HDU 5402 Travelling Salesman Problem(棋盘染色 构造 多校啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5402 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 corn

hdu 5402 Travelling Salesman Problem (构造)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5402 题意:给定N*M的矩阵,每一格子里面有一个非负整数,求从(1,1)到(n,m)这条路上的和,(每个格子只能走一次,求最大的和). 分析:官方题解当N为奇数或M为奇数时,可以遍历到所有格子.当N和M都为偶数的时候,那么讲棋盘黑白染色,假设 (1,1)(1,1)和(n,m)(n,m)都为黑色,那么这条路径中黑格个数比白格个数多11,而棋盘中黑白格子个数相同,所以必然有一个白格不会被经过,所以选择白格中

hdu 5402 Travelling Salesman Problem (技巧) 未写完-------------------------------

题意:给一个n*m的矩阵,每个格子中有一个数字,每个格子仅可以走一次,问从(1,1)走到(n,m) 的路径点权之和. 思路: 想了挺久,就是有个问题不能短时间证明,所以不敢下手. 显然只要n和m其中一个是奇数,逐行/列绕就可以到达终点,可是恰好都是偶数呢?由于绕不到,那至少得舍弃1个,但是弃哪个比较好?况且有些格子是弃不了的(画4*4的模拟就知道了). 通过画图可以知道(自己绕!),行号+列号为奇数的格子都是可以舍弃的,而且可以保证其他所有格子都能走一遍到终点(无论是从行/列为单位来绕,这个图都

hdu 5402 Travelling Salesman Problem

题意:从一个方格的左上角走到右下角,拿起经过的全部数字,且每一个方格最多仅仅能走一次,问,终于到达右下角时,sum最大是多少. 做法:--非常显然构造了 首先假设nn为奇数或者mm为奇数,那么显然能够遍历整个棋盘. 如果n,mn,m都为偶数,那么将棋盘黑白染色,如果(1,1)(1,1)和(n,m)(n,m)都为黑色,那么这条路径中黑格个数比白格个数多11.而棋盘中黑白格子个数同样.所以必定有一个白格不会被经过,所以选择白格中权值最小的不经过. 构造方法是这样.首先RRRRDLLLLD这种路径走到