题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5402
3 3 2 3 3 3 3 3 3 3 2
25 RRDLLDRR
题意:
有一个n*m的迷宫,每一个格子都有一个非负整数,一个人要从迷宫的左上角(1,1)走到迷宫的右下角(n,m),
而且要使他经过的路径的和最大,
求最大和为多少并且输出他所走的路径。
官方题解:
首先如果n为奇数或者m为奇数,那么显然可以遍历整个棋盘。
如果n,m都为偶数,那么讲棋盘黑白染色,假设(1,1)和(n,m)都为黑色,那么这条路径中黑格个数比白格个数多1,而棋盘中黑白格子个数相同,所以必然有一个白格不会被经过,所以选择白格中权值最小的不经过。
构造方法是这样,首先RRRRDLLLLD这样的路径走到这个格子所在行或者上一行,然后DRUR这样走到这个格子的所在列或者前一列,然后绕过这个格子。然后走完这两行,接着按LLLLDRRRR这样的路径往下走。
再贴一个讲解很详细的链接:http://blog.csdn.net/queuelovestack/article/details/47756605
代码如下:
#include <cstdio> int n, m; int a[117][117]; int sum; int min_x, min_y; void build_1()//都是偶数 { printf("%d\n",sum-a[min_x][min_y]); for(int i = 1; i <= n; i+=2) { if(min_x==i || min_x==i+1) { for(int j = 1; j < min_y; j++) { if(j&1) printf("D"); else printf("U"); printf("R"); } if(min_y < m) printf("R"); for(int j = min_y+1; j <= m; j++) { if(j&1) printf("U"); else printf("D"); if(j < m) printf("R"); } if(i < n-1) printf("D"); } else if(min_x > i)//上面 { for(int j = 1; j < m; j++) printf("R"); printf("D"); for(int j = m; j > 1; j--) printf("L"); printf("D"); } else//下面 { for(int j = m; j > 1; j--) printf("L"); printf("D"); for(int j = 1; j < m; j++) printf("R"); if(i < n-1) printf("D"); } } printf("\n"); } void build_2() { printf("%d\n",sum); if(n&1)//如果n是奇数,先走偶数方向 { for(int i = 1; i <= n; i++) { for(int j = 1; j < m; j++) { if(i&1) printf("R"); else printf("L"); } if(i < n) printf("D"); else printf("\n"); } } else { for(int i = 1; i <= m; i++) { for(int j = 1; j < n; j++) { if(i&1) printf("D"); else printf("U"); } if(i < m) printf("R"); else printf("\n"); } } } int main() { while(~scanf("%d%d",&n,&m)) { sum=0; min_x = 1; min_y = 2; 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)&1) && (a[min_x][min_y]>a[i][j]))//坐标和为奇数且最小 { min_x = i; min_y = j; } } } if(!(n&1) && !(m&1))//都是偶数 { build_1(); } else { build_2(); } } return 0; } /* 3 3 2 3 3 3 3 3 3 3 2 */