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

大致题意:n*m的非负数矩阵,从(1,1) 只能向四面走,一直走到(n,m)为终点,路径的权就是数的和,输出一条权值最大的路径方案

思路:由于这是非负数,要是有负数就是神题了,要是n,m中有一个是奇数,显然可以遍历,要是有一个偶数,可以画图发现,把图染成二分图后,(1,1)为黑色,总能有一种构造方式可以只绕过任何一个白色的点,然后再遍历其他点,而绕过黑色的点必然还要绕过两个白色点才能遍历全部点,这是画图发现的,所以找一个权值最小的白色点绕过就可以了,

题解给出了证明:

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


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
#define rep(i,n) for ( int i=0; i< int(n); i++ )
using namespace std;
typedef long long ll;
#define X first
#define Y second
typedef pair<int,int> pii;

template <class T>
inline bool RD(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
template <class T>
inline void PT(T x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) PT(x / 10);
    putchar(x % 10 + '0');
}

const int N = 123;
int mp[N][N];
int main(){

        int n,m;
        while(~scanf("%d%d",&n,&m)){
                int sum = 0;
                memset(mp,0,sizeof(mp));
                REP(i,n) REP(j,m) RD(mp[i][j]), sum += mp[i][j];
                if( (n&1)||(m&1) ){
                        PT(sum);puts("");
                        if( n&1 ){
                                REP(r,n){
                                        if( r&1 ) REP(i,m-1) putchar('R');
                                        else REP(i,m-1) putchar('L');
                                        if( r != n) putchar('D');
                                }
                        }else{
                                REP(c,m){
                                        if( c&1 ) REP(i,n-1) putchar('D');
                                        else REP(i,n-1) putchar('U');
                                        if( c != m) putchar('R');
                                }
                        }
                }else{
                        int minn = 1LL<<30;
                        int sx,sy;
                        REP(x,n) REP(y,m){
                                if( (x+y)&1 ){
                                        if( mp[x][y] < minn) minn = mp[x][y], sx = x,sy = y;
                                }
                        }
                        printf("%d\n",sum-minn);
                        bool ok = 0;
                        REP(y,m){
                                if( (y-1)/2+1 == (sy-1)/2+1){
                                        ok = 1;
                                        bool rgt = 1;
                                        REP(x,n){
                                                if( x == sx) {
                                                        if( x != n) putchar('D');
                                                        continue;
                                                }
                                                if( rgt) putchar('R');
                                                else putchar('L');
                                                if( x != n) putchar('D');
                                                rgt = !rgt;
                                        }
                                        y++;
                                }else{
                                        if( ((y&1)&&ok==0) || ((y%2 == 0)&&ok) ){
                                                REP(x,n-1) putchar('D');
                                        }else{
                                                REP(x,n-1) putchar('U');
                                        }
                                }
                                if( y != m) putchar('R');
                        }
                }
                puts("");
        }
}

Travelling Salesman Problem

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

Total Submission(s): 864    Accepted Submission(s): 313

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

Recommend

wange2014

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

时间: 2024-10-12 14:20:33

HDU 5402 Travelling Salesman Problem (构造)(好题)的相关文章

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(模拟题)

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

构造 - 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: 首先,因为每个格子都是非负整数,而且规定每个格子只能走一次,所以为了使和尽可能大,必定是走的格子数越多越好.这样我们就需

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 colum

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

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

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

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

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

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