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