zoukankan      html  css  js  c++  java
  • 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:做完之后的表情
  • 相关阅读:
    Eclipse快捷键大全(转载)
    IE9浏览Flash页面时显示错位并不停地闪烁
    flash全屏事件和键盘按下事件部分不能触发问题
    AS3摘要(转载)
    【as3手册小记】ActionScript 中处理全屏模式的注意事项
    巧用FlashPaper 让Word文档变Flash
    AS3视频照相截图(转载)
    Json串到json对象的转换
    映射文件详解(转)
    Jquery .ajax方法分析(一)
  • 原文地址:https://www.cnblogs.com/ck666/p/7462510.html
Copyright © 2011-2022 走看看