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): 872    Accepted Submission(s): 316
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,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

题目大意就是给你一个都是非负元的矩阵,从左上走到右下要求所走过的数字之和最大。
题目很简单,写起来并不简单。
做法就是走过的格子数越多越好。行和列只要有一个是奇数就能够将格子走完,这个不用说了。
难点就在于行和列都是偶数,这就是黑白棋盘问题。
如果把棋盘中的每个格子都给一个属性,行+列能被2整除的叫做黑格,不能被2整除的叫白格,就构造出来像国际象棋一样的棋盘。(可以画一画看看)
我们知道共有偶数个格子,而且左上和右下的格子都是相同颜色的黑格,因此要想尽可能的多走格子的话,这条路径上的黑格必定和白格的数量相差 1 。
因此最少最少有一个格子没有走,而且一定要是白格(想想为什么!)。所以要找出所有的白格中最小的那个选择不走。

选择格子的问题结束了,然后就是怎么走的问题,这里借鉴了别人的意见,然后代码量减少了一半(不得不佩服别人,自己还是图样图森破)。
不管怎么样先左右左右的走到那个不走格子的上一行或者上两行,这个就取决于这个点横坐标的奇偶性了。

偶数行的情况:
奇数行的情况:
这样只要特殊处理下不走的格子的那两行的走法,然后其余行都是左右左右的走就可以了。

AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

#define SIZE 500
using namespace std;
#define INF 0xf3f3f3
typedef long long ll;

ll n,m;
ll ans,minn;
ll Map[SIZE][SIZE];
int x,y;
void input()
{
    minn = INF;
    ans = 0;
    for(int i = 0 ; i < n ; i ++)
    {
        for(int j = 0 ; j < m ; j ++)
        {
            scanf("%I64d",&Map[i][j]);
            ans += Map[i][j];
            if((i+j)%2)     //假定首尾为黑格子,则删除白格子中值最小的那个
            {
                if((i==0&&j==0) || (i==n-1 && j==m-1))
                    continue;
                if(minn >= Map[i][j])
                {
                    minn = Map[i][j];
                    x = i;
                    y = j;
                }
            }
        }
    }
}

void work3(int n,int m,int r,int c)
{
	int len=r/2;
	for(int i=0;i<len;i++)
	{
		for(int j=0;j<m-1;j++)
			putchar('R');
		putchar('D');
		for(int j=0;j<m-1;j++)
			putchar('L');
		putchar('D');
	}
	len=c/2;
	for(int i=0;i<len;i++)
		printf("DRUR");
	if(r&1)
		printf("RD");
	else
		printf("DR");
	len=m/2;
	for(int i=c/2+1;i<len;i++)
		printf("RURD");
	len=n/2;
	for(int i=r/2+1;i<len;i++)
	{
		putchar('D');
		for(int j=0;j<m-1;j++)
			putchar('L');
		putchar('D');
		for(int j=0;j<m-1;j++)
			putchar('R');
	}
}
int main()
{
    freopen("in6.txt","r",stdin);
    freopen("out6.txt","w",stdout);
    while(scanf("%I64d%I64d",&n,&m)!=EOF)
    {
        input();
        if(n%2==0&&m%2==0)
        {
            ans -= minn;
            printf("%I64d\n",ans);
            work3(n,m,x,y);
            printf("\n");
        }
        else if(n%2==0&&m%2!=0)     //偶数行、奇数列 竖着走
        {
            printf("%I64d\n",ans);
            for(int i = 0 ; i < m ; i ++)
            {
                if(i%2 == 0)     //偶数列往下走 (从第0行开始,所以从偶数行开始计)
                {
                    for(int j = 0 ; j < n-1 ; j ++)
                        printf("D");
                    if(i != m-1)    //最后一个点不走
                        printf("R");
                }
                else        //奇数列往上走
                {
                    for(int j = 0 ; j < n-1 ; j ++)
                        printf("U");
                    printf("R");
                }
            }
            printf("\n");
        }
        else        //奇数行、偶数列 横着走 (奇数列、奇数行随便走)
        {
            printf("%I64d\n",ans);
            for(int i = 0 ; i < n; i ++)
            {
                if(i%2 == 0)     //偶数行往右走
                {
                    for(int j = 0 ; j < m-1 ; j ++)
                        printf("R");
                    if(i!=n-1)
                        printf("D");
                }
                else
                {
                    for(int j = 0 ; j < m-1 ; j ++)
                        printf("L");
                    printf("D");
                }
            }
            printf("\n");
        }
    }
    return 0;
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值