博客园 首页 私信博主 显示目录 隐藏目录 管理

hdu5402:Travelling Salesman Problem

 Travelling Salesman Problem

 

2017-09-01


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

INPUT_1
3 3
2 3 3
3 3 3
3 3 2
INPUT_2
2 2
1 0
1 1
INPUT_3
4 4
6 0 6 6
6 6 6 6
6 6 6 6
6 6 6 6

Sample Output

OUT_1
25
RRDLLDRR
OUT_2
3
DR
OUT_3
90
DRRURDDLLLDRRR
DDDRUURURDDLDR皆可。。
spj.....

此题是一个好大的模拟,出题人你节操被10万买走了吧
题意:给你一个大矩阵,一笔从(1,1)走到(n,m)路径上最大的和.
看出来结论:如果n||m有一个是奇数,那么就可以走所有的点,怎么走看心情
n和m全为偶数就找到一个i,j(1<=i<n;1<=j<=m)&&(i+j)是奇数的点,是绕过这个看不顺的点走到(n,m)
路程全部模拟;每一行只走一个方向的可以用数学算出来poi
要不是掉rating我才不干呢,什么破玩意
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int read(){
    char ch=getchar();
    int f=1,an=0;
    while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
    while('0'<=ch&&ch<='9'){an=an*10+(ch-'0');ch=getchar();}
    return an*f;
}
int n,m,sum;
int x,y,z;
int a[100+99][100+99];
void P1(int n,int m){
    cout<<sum<<endl;
    for(int i=1;i<=n;i++){
        if(i&1){
            for(int j=1;j<m;j++)cout<<"R";if(i!=n)cout<<"D";}
        else {
            for(int j=1;j<m;j++)cout<<"L";if(i!=n)cout<<"D";}
    }
    cout<<endl;
}
void P2(int n,int m){
    cout<<sum<<endl;
    for(int i=1;i<=m;i++){
        if(i&1){
            for(int j=1;j<n;j++)cout<<"D";if(i!=m)cout<<"R";}
        else{
            for(int j=1;j<n;j++)cout<<"U";if(i!=m)cout<<"R";}
    }
    cout<<endl;
}
void P5(int a,int b,int c,int d){
    int e=a;
    e=(e-1)>>1;
    for(int i=1;i<=e;i++){
        for(int j=1;j<d;j++)cout<<"R";cout<<"D";
        for(int j=1;j<d;j++)cout<<"L";cout<<"D";}
    int k=1,z=1;bool flag=1;
    while(z<d){
        if(z==b){cout<<"R";z++;}
        else{
            if(flag){cout<<"DR";flag^=1;z++;}
            else {cout<<"UR";flag^=1;z++;}
        }
    }
    if(b!=m)cout<<"D";
    c>>=1;c-=e;
    for(int i=2;i<=c;i++){
        if(i==2)cout<<"D";
        for(int j=1;j<d;j++)cout<<"L";cout<<"D";
        for(int j=1;j<d;j++)cout<<"R";if(i!=c)cout<<"D";}
}
void P3(int n,int m){
    cout<<sum-a[x][y]<<endl;
    P5(x,y,n,m);
    cout<<endl;
}
void G(){sum=0;n=m=0;}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        z=9999999;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){a[i][j]=read();sum+=a[i][j];
            if((i+j)&1)if(z>a[i][j]){z=a[i][j];x=i;y=j;}
        }
        if(n&1)P1(n,m);
        else if(m&1)P2(n,m);
        else P3(n,m);
        G();
    }
    return 0;
}
有节操模拟

by:s_a_b_e_r


 什么破玩意+1
题意见上边(实力甩锅
n或者m任意一个是奇数的话就一笔画走完这个矩形
两个都是偶数的话就麻烦了x
要在矩阵上去掉一个点
但是不是所有点都能去
4x4的点图如下

A X C X
X C X C
C X C X
X C X B

其中X是可以去掉的点,C是不能去掉的点
关于怎么去点……这个做法很多啊w
表示可以每次扫两行
两行内都没有要去掉的点的话就直接走直线
有的话就扭过去x
大概这样
  →      →
↑  ↓→↑     ……
……我自己都看不懂了x
然后最后特判一下收尾部分
如果要去掉的点恰好在最后一行的话,那么最后应该是→结尾
否则应该是↓结尾
还有因为这两行是从左到右处理的,下一行(如果有的话)要扫回去
……总之这东西好难写的说>_<调了好久
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,a[109][109],sum,minn=1000000,ai,aj;
int read(){
    char ch=getchar();
    int f=1,an=0;
    while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
    while('0'<=ch&&ch<='9'){an=an*10+(ch-'0');ch=getchar();}
    return an*f;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
      sum=0;
      minn=1000000;
      for(int i=1;i<=n;++i)
      for(int j=1;j<=m;++j)
      {
        a[i][j]=read();
        sum+=a[i][j];
        if(((i+j)%2)&&a[i][j]<minn)
        {minn=a[i][j];ai=i,aj=j;}
      }
      if(n%2||m%2)
      {
        cout<<sum<<endl;
        if(n%2)
        {
          for(int i=1;i<=n/2;++i)
          {
            for(int j=1;j<m;++j)cout<<"R";
            cout<<"D";
            for(int j=1;j<m;++j)cout<<"L";
            cout<<"D";
          }
          for(int j=1;j<m;++j)cout<<"R";
        }
        else
        {
          for(int i=1;i<=m/2;++i)
          {
            for(int j=1;j<n;++j)cout<<"D";
            cout<<"R";
            for(int j=1;j<n;++j)cout<<"U";
            cout<<"R";
          }
          for(int j=1;j<n;++j)cout<<"D";
        }
      }
      else
      {
        cout<<sum-a[ai][aj]<<endl;
        for(int xx=1;xx<=n;xx+=2)
        if(xx==ai||xx+1==ai)
        {
            for(int yy=1;yy<m-1;)
            {
                if(yy!=aj){cout<<"DR";}
                else {cout<<"R";if(yy<m)cout<<"DR";}
                ++yy;
                if(yy==m-1)break;
                if(yy!=aj){cout<<"UR";}
                else {cout<<"R";if(yy<m)cout<<"UR";}
                ++yy;
            }
            if(aj==m)cout<<"DR";
            else if(aj==m-1)cout<<"RD";
            else cout<<"D";
            xx+=1;
            if(xx<n)
            {
              cout<<"D";
              for(int i=1;i<m;++i)cout<<"L";
              cout<<"D";
            }    
        }
        else
        {
            for(int j=1;j<m;++j)cout<<"R";
            if(xx==n)continue;
            cout<<"D";
            for(int j=1;j<m;++j)cout<<"L";
            cout<<"D";
        }
      }
      cout<<endl;
    }
    return 0;
}
hdu5402

by:wypx


w:发现这题是模拟的时候的表情
S:做完之后的表情
posted @ 2017-09-01 11:43  ck666  阅读(122)  评论(0编辑  收藏  举报