3 3 2 3 3 3 3 3 3 3 2
25 RRDLLDRR
题目大意:给出一个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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5402 Travelling Salesman Problem (模拟 有规律)
原文地址:http://blog.csdn.net/yanghuaqings/article/details/47777103