hdu 5402 Travelling Salesman Problem (构造)

来源:互联网 发布:梦幻西游手游 for mac 编辑:程序博客网 时间:2024/05/24 00:07

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5402

题意:给定N*M的矩阵,每一格子里面有一个非负整数,求从(1,1)到(n,m)这条路上的和,(每个格子只能走一次,求最大的和)。

分析:官方题解当N为奇数或M为奇数时,可以遍历到所有格子。当N和M都为偶数的时候,那么讲棋盘黑白染色,假设

(1,1)(1,1)(n,m)(n,m)都为黑色,那么这条路径中黑格个数比白格个数多11,而棋盘中黑白格子个数相同,所以必然有一个白格不会被经过,所以选择白格中权值最小的不经过。构造方法是这样,首先RRRRDLLLLD这样的路径走到这个格子所在行或者上一行,然后DRUR这样走到这个格子的所在列或者前一列,然后绕过这个格子。然后走完这两行,接着按LLLLDRRRR这样的路径往下走。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>using namespace std;const int maxn = 1e3;int G[maxn][maxn];int Sum,move_x,move_y;void CoverRow(int n,int m) //行{int cur_x=1,cur_y=1;while(true){while(cur_y+1<=m){cur_y++;putchar('R');if(cur_x==n && cur_y==m)return ;}if(cur_x==n && cur_y==m)return ;putchar('D');cur_x++;while(cur_y-1>=1){cur_y--;putchar('L'); }putchar('D');cur_x++;}}void CoverColumn(int n,int m)  //列{int cur_x=1,cur_y=1;while(true){while(cur_x+1<=n){cur_x++;putchar('D');if(cur_x==n && cur_y==m)return ;}if(cur_x==n && cur_y==m)return ;putchar('R');cur_y++;while(cur_x-1>=1){cur_x--;putchar('U');}putchar('R');cur_y++;}}void solve(int n,int m){int cur_x=1,cur_y=1;while(cur_x+1<move_x){while(cur_y+1<=m){cur_y++;putchar('R');}cur_x++;putchar('D');if(cur_x+1<move_x){while(cur_y-1>=1){cur_y--;putchar('L');}cur_x++;putchar('D');}}//printf("cur :%d %d\n",cur_x,cur_y);//system("pause");if(cur_y==1){string str("#DRU");int len=(m-2)/2,i;for(i=1;i<=len;i++)str+="RDRU";bool fg=false;for(i=1;i<str.size();i++){if(fg){if(str[i]=='D'){putchar('U');cur_x--;}else if(str[i]=='U'){putchar('D');cur_x++;}else{putchar(str[i]); cur_y++;}}else{if(str[i]=='R'){cur_y++;putchar('R');}else if(str[i]=='D'){cur_x++;if(cur_x==move_x && cur_y==move_y){cur_x--;fg=true;continue ;}putchar('D');} else{cur_x--;if(cur_x==move_x && cur_y==move_y){cur_x++;fg=true;continue ; }putchar('U');}}}}else{string str("#DLU");int len=(m-2)/2,i;for(i=1;i<=len;i++)str+="LDLU";bool fg=false;for(i=1;i<str.size();i++){if(fg){if(str[i]=='L'){putchar('L');cur_y--;}else if(str[i]=='D'){putchar('U');cur_x--;}else{putchar('D');cur_x++;}}else{if(str[i]=='L'){cur_y--;putchar('L'); }else if(str[i]=='D'){cur_x++;if(cur_x==move_x && cur_y==move_y){cur_x--;fg=true;continue ;}putchar('D');}else{cur_x--;if(cur_x==move_x && cur_y==move_y){cur_x++;fg=true;continue ;}putchar('U');} }}}//printf("Part2 cur:%d %d\n",cur_x,cur_y);//system("pause");if(cur_x==n && cur_y==m){putchar('\n');return  ;}cur_x++;putchar('D');while(true){if(cur_y==1){for(int i=2;i<=m;i++){cur_y++;putchar('R'); }if(cur_x==n && cur_y==m){putchar('\n');return  ;}cur_x++;putchar('D');}else{for(int i=2;i<=m;i++){cur_y--;putchar('L');}cur_x++;putchar('D');}}putchar('\n');}void getmove(int n,int m){int Min=2e9,i,j;for(i=1;i<=n;i+=2){for(j=2;j<=m;j+=2){if(G[i][j]<Min){Min=G[i][j];move_x=i;move_y=j; }}}for(i=2;i<=n;i+=2){for(j=1;j<=m;j+=2){if(G[i][j]<Min){Min=G[i][j];move_x=i;move_y=j;}}}Sum-=Min;}int main(){int i,j,m,n;while(scanf("%d%d",&n,&m)==2){Sum=0;for(i=1;i<=n;i++)for(j=1;j<=m;j++){scanf("%d",&G[i][j]);Sum+=G[i][j];}if(n&1 || m&1){printf("%d\n",Sum);if(n&1)CoverRow(n,m);elseCoverColumn(n,m);putchar('\n');continue ;}getmove(n,m);printf("%d\n",Sum);//printf("move : %d %d\n",move_x,move_y);//system("pause");solve(n,m);}return 0;} 


0 0
原创粉丝点击