一、题目描述:机器人R在一个有n×n个方格区域F中收集样本。(i,j)方格中样本的
价值为v(i,j),如图所示,R从方形区域F的左上角A点出发,向下或向右行走,直到右
下角的B点,在走过的路上,收集方格中的样本。R从A点到B点共走2次,试找出R的
2条行走路径,使其取得的样本总价值最大。
二、题目分析
性质1:机器人R从A点走到B点的一条路径的方格数为2*n-1
证明:A点的坐标是(1,1),B点的坐标是B(n, n),从A点走到B点,按照向下或向右行走的规则,则A必须向下和向左各跨n-1个方格,再加上原来在起点(1,1)的那个方格,所以A点走到B点的一条路径的方格数为 2*(n-1)+1=2*n-1;
性质2:记机器人R的当前坐标是N(X,Y),从起点A到当前点N的路径方格数是Steps,则有Steps=X+Y—1
证明:因为A、N的坐标分别为(1,1)和(X,Y),所以从起点A到N向下走的步数和是X-1,向右走的步数和是Y-1,再加上原来在起点(1,1)的那个方格,则从起点A到当前点N的路径方格数为: X-1+Y-1+1=X+Y-1
三、题目解答
此题可用动态规划解答,机器人走的步数将问题划分为2*n-1个状态,题目要求R从A到B共走两次,如果分两次来走的话,一个就是效率低下问题,另一个就是难以标记那些点是在第一次已经走过,对重复走两次的点所造成的误差难以消除。有个办法就是同时走两条路径,当两条路径走到相同一点时,只对相同点取值一次。由性质2我们知道,在一定的Steps的情况下,如果知道当前点的X轴坐标,就可以知道Y轴坐标Y=Steps—X+1,所以可以记M[Steps][x1][x2]为两条路径同时走Steps步的情况下,到达(x1,y1)(x2,y2)所取的当前最大值。由于机器人只能向下和向左走,那么在(x1,y1)(x2,y2)的前一个状态就是一下四种之一:
(x1,y1-1)(x2,y2-1);
(x1,y1-1)(x2-1,y2);
(x1-1,y1)(x2-1,y2)
(x1-1,y1)(x2,y2-1)
当(x1,y1)(x2,y2)是不同点的情况下,状态转移方程如下:
M[Steps][x1][x2]=max{M[steps-1][x1][x2]+v[x1][y1]+v[x2][y2],
M[steps-1][x1][x2-1]+v[x1][y1]+v[x2][y2],
M[steps-1][x1-1][x2]+v[x1][y1]+v[x2][y2],
M[steps-1][x1-1][x2-1]+v[x1][y1]+v[x2][y2]}
当(x1,y1)(x2,y2)是相同点的情况下,状态转移方程如下:
M[Steps][x1][x2]=max{M[steps-1][x1][x2]+v[x1][y1],
M[steps-1][x1][x2-1]+v[x1][y1],
M[steps-1][x1-1][x2]+v[x1][y1],
M[steps-1][x1-1][x2-1]+v[x1][y1] }
实现代码如下:
#include<iostream>
using namespace std;
#define Max_n 50
#define Max_s 2*50-1
int M[Max_s][Max_n][Max_n];
int v[Max_n][Max_n];
int max(int a,int b)
{
return a>b?a:b;
}
void MaxValue(int steps,int x1,int x2,int &value)
{
int y1=steps+1-x1;
int y2=steps+1-x2;
if(x1==x2)
value=max( M[steps][x1][x2]+v[x1][y1],value);
else
value=max( M[steps][x1][x2]+v[x1][y1]+v[x2][y2],value);
}
int main()
{
int n;//图的规模
int nodes;//图中有值的点的个数
int value,steps;//
cin>>n>>nodes;
memset(M,0,sizeof(M));
memset(v,0,sizeof(v));
for(int i=0;i<nodes;i++)
{
int c,r,val;
cin>>c>>r>>value;
v[c][r]=val;
}
M[1][1][1]=v[1][1];
for(steps=2;steps<=2*n-1;steps++)
for(int x1=1;x1<=steps;x1++)
for(int x2=1;x2<=steps;x2++)
{
value=0;
MaxValue(steps-1,x1,x2,value);
MaxValue(steps-1,x1,x2-1,value);
MaxValue(steps-1,x1-1,x2,value);
MaxValue(steps-1,x1-1,x2-1,value);
M[steps][x1][x2]=value;
}
cout<<M[2*n-1][n][n]<<endl;
// system("pause");
}
以上代码经过GC++ 调试,
样题输入样例:
9
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
输出:
67