多校第九場Travelling Salesman Problem總結

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

題意:n*m的矩陣格子,每個格子有相應的數字,上要從矩陣的左上角走到右下角,要求使得走過的數字之和儘可能多,同時每個格只能走一次,輸出走過的數字之和,以及路徑

思路:對於n,m任何一個是奇數,那麼就能經過所有的格子,如果n,m兩個數都是偶數,那麼那麼講棋盤黑白染色,假設(1,1)和(n,m)都爲黑色,那麼這條路徑中黑格個數比白格個數多1,而棋盤中黑白格子個數相同,所以必然有一個白格不會被經過,所以選擇白格中權值最小的不經過。
構造方法是這樣,首先RRRRDLLLLD這樣的路徑走到這個格子所在行或者上一行,然後DRUR這樣走到這個格子的所在列或者前一列,然後繞過這個格子。然後走完這兩行,接着按LLLLDRRRR這樣的路徑往下走。

代碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 100005;
int a[111][111];
int main()
{
    int n,m;
    int x,y;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int mi=inf;
        ll sum=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            sum+=a[i][j];
            if((i+j)%2==1)
            {
               if(a[i][j]<mi)
               {
                   mi=a[i][j];
                x=i;
                y=j;
               }
            }
        }
        if(n%2==1)
        {
            printf("%lld\n",sum);
            for(int i=1;i<=n;i++)
            {
                if(i%2)
                    for(int j=2;j<=m;j++)printf("R");
                else
                    for(int j=2;j<=m;j++)printf("L");
                if(i!=n)
                        printf("D");
            }
            printf("\n");
        }
        else if(m%2)
        {
            printf("%lld\n",sum);
            for(int i=1;i<=m;i++)
            {
                if(i%2)
                    for(int j=2;j<=n;j++)printf("D");
                else
                    for(int j=2;j<=n;j++)printf("U");
                if(i!=m)
                        printf("R");
            }
            printf("\n");
        }
        else
        {
           printf("%lld\n",sum-mi);
          for(int i=1;i<(x+1)/2;i++)
          {
                    for(int j=2;j<=m;j++)printf("R");
                      printf("D");
                    for(int j=2;j<=m;j++)printf("L");
                        printf("D");
          }
          for(int i=1;i<(y+1)/2;i++)
              printf("DRUR");
          if(x%2)
            printf("DR");
           else
            printf("RD");
        for(int i=(y+1)/2;i<m/2;i++)
            printf("RURD");
        for(int i=(x+1)/2;i<n/2;i++)
          {
               printf("D");
                    for(int j=2;j<=m;j++)printf("L");
                printf("D");
                    for(int j=2;j<=m;j++)printf("R");
          }
          printf("\n");
        }
    }
    return 0;
}
/*
4 4
2 2 2 2
1 2 2 2
2 2 2 2
2 2 2 2
4 4
2 1 2 2
2 2 2 2
2 2 2 2
2 2 2 2
4 4
2 2 2 1
2 2 2 2
2 2 2 2
2 2 2 2
4 4
2 2 2 2
2 2 1 2
2 2 2 2
2 2 2 2
4 4
2 2 2 2
2 2 2 2
2 1 2 2
2 2 2 2
4 4
2 2 2 2
2 2 2 2
2 2 2 1
2 2 2 2
4 4
2 2 2 2
2 2 2 2
2 2 2 2
1 2 2 2
*/

 咦咦咦~wa了一發之後,試了幾乎所有的樣例、、、

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章