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(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的棋盘,每一个小方格内有一个数值,问从左上角走到右下角,经过的方格的数值和最大是多少。(每个方格只能走一次)


解题思路:

首先如果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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值