2015 Multi-University Training Contest 9_1007(模拟)

Travelling Salesman Problem

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 143    Accepted Submission(s): 57
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(1n,m100,nm2) .

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,y1) , "R" means you walk to cell (x,y+1) , "U" means you walk to cell (x1,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
 

题意:给你一个n*m的矩阵,每个点都有其对应的值,从(1,1)开始走到(n,m)所能得到的值总和最大是多少?(一个点只能走一次)

分析:恶心模拟。比赛的时候没有模拟出来。神马都是浮云。解法大概和题解的差不多。

(1)如果n*m是奇数,那么所有的点都能走完,路径也很好输出。

(2)如果n*m是偶数,那么就得舍弃一个点,但是并不是所有的点都可以舍弃,只有当点(x,y)满足x*y是奇数的时候才可以舍弃,题意求最大值,那么事先把最小的可删点的值与坐标记录下来,然后跑路径的时候绕过它就好了。假设不走的点是(X,Y),那么:

a)当Y==1时,把1、2列单独拿出来,绕过(X,Y)走完之后,一定是走到了点(n,2),然后往右走一格就进入了右边剩下的n*(m-2)的矩阵,先向上到顶,然后向右一格,向下走到底,向右走一格……依次类推就能走到终点;

b)把第Y-1、Y列单独拿出来,第1~Y-2列可以很好走完,先向下到底,然后向右一格,然后向上到顶,再向右……依次类推,

当Y是偶数时,那么之前最后走到的点是(1,Y-2),向右走一格进入(1,Y-1),然后Y-1、Y两列可以绕过(X,Y)走完,最终走到(n,Y),往右走一格进入右边剩下的n*(m-Y)的矩阵,此时n*(m-Y)是偶数,由于是从左下角进入矩阵的,那么可以,先向上走到顶,向右一格,向下到底……依次类推,一定可达终点;

当Y是奇数时,那么之前最后走到的点是(n,Y-2),向右走一格进入(n,Y-1),然后Y-1、Y两列可以绕过(X,Y)走完,最终走到(1,Y),往右走一格进入右边剩下的n*(m-Y)的矩阵,此时n*(m-Y)是奇数,于是像(1)一样走就好。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5402

代码清单:

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<cctype>
#include<string>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int maxn = 100 + 5;

int n,m;
int X,Y;
int data;

int main(){
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    while(scanf("%d%d",&n,&m)!=EOF){
        int ans=0;
        int minn=100000;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&data);
                ans+=data;
                if(((i+j)&1)&&!(i==n&&j==m)){
                    if(data<minn){
                        X=i; Y=j;
                        minn=data;
                    }
                }
            }
        }
        if(n&1){
            printf("%d\n",ans);
            for(int i=0;i<n;i++){
                if(i) printf("D");
                for(int j=1;j<m;j++){
                    if(i&1) printf("L");
                    else printf("R");
                }
            }printf("\n");
        }
        else if(m&1){
            printf("%d\n",ans);
            for(int i=0;i<m;i++){
                if(i) printf("R");
                for(int j=1;j<n;j++){
                    if(i&1) printf("U");
                    else printf("D");
                }
            }printf("\n");
        }
        // n*m是偶数
        else{
            printf("%d\n",ans-minn);

            //先把左边n*(Y-2)的矩阵走完
            for(int i=0;i<Y-2;i++){
                if(i) printf("R");
                for(int j=1;j<n;j++){
                    if(i&1) printf("U");
                    else printf("D");
                }
                if(i==Y-3) printf("R");
            }
            //当Y是偶数
            if(!(Y&1)){
                for(int i=1;i<=X;i++){
                    if(i>1) printf("D");
                    if(i==X) break;
                    if(i&1) printf("R");
                    else printf("L");
                }
                for(int i=X+1;i<=n;i++){
                    printf("D");
                    if(i&1) printf("L");
                    else printf("R");
                }
                for(int i=1;i<=m-Y;i++){
                    printf("R");
                    for(int j=1;j<n;j++){
                        if(i&1) printf("U");
                        else printf("D");
                    }
                }printf("\n");
            }
            else{
                //当Y==1的情况
                if(Y==1){
                    for(int i=1;i<=X;i++){
                        if(i>1) printf("D");
                        if(i==X) break;
                        if(i&1) printf("R");
                        else printf("L");
                    }
                    for(int i=X+1;i<=n;i++){
                        printf("D");
                        if(i&1) printf("L");
                        else printf("R");
                    }
                    Y=Y+1;
                    for(int i=1;i<=m-Y;i++){
                        printf("R");
                        for(int j=1;j<n;j++){
                            if(i&1) printf("U");
                            else printf("D");
                        }
                    }printf("\n");
                }
                //当Y是奇数
                else{
                    for(int i=n;i>=X;i--){
                        if(i<n) printf("U");
                        if(i==X) break;
                        if(i&1) printf("L");
                        else printf("R");
                    }
                    for(int i=X-1;i>=1;i--){
                        printf("U");
                        if(i&1) printf("R");
                        else printf("L");
                    }
                    for(int i=1;i<=m-Y;i++){
                        printf("R");
                        for(int j=1;j<n;j++){
                            if(i&1) printf("D");
                            else printf("U");
                        }
                    }printf("\n");
                }
            }
        }
    }return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值