分析
这道题和NOIP2000的方格取数如出一辙(超详细题解在此),都是给定矩阵,要求从左上角走到最下角(只可向右或向左走)找两条路径,使两条路径上数字的总和最大。但这题有几个变化:
- 路径不可相交。
- 矩阵形态不一样:原题是方阵,这题是任意矩阵。(但这个变化没有什么影响)
- 数据范围有所扩大:原题是9以内,这题是50。(但如果用动规做,O(n3)的时间复杂度依旧不会超时)
解法依然是动规,两条路线同时走,状态是[y1][x1][y2][x2]表示两条路线分别走到(x1,y1)和(x2,y2)……阶段、状态转移方程也都一样,省略100~200字…….只是为了确保路径不可相交,不妨设路线1始终在路线2的左侧,可以加上x1<x2这个限制条件来保证。
代码大体一样,复杂度也一样,时间复杂度O(n3),空间复杂度O(n4)。
代码
注意
- 状态转移时,要判断上一状态是否在边界内、是否合法。
- 如果对最后一轮也加了x1<x2限制,最后状态不再是求[m][n][m][n],而是[m][n-1][m-1][n](倒数第二轮的状态),路线1的终点和路线2的终点只有这一种可能,一条到达终点左边一格,另一条到达终点上边一格。
- 当m或n为1时,无法找到两个不相交路径,需输出0。
#include <stdio.h>
#include <string.h>
int max(int a,int b) {
return a>b?a:b;}
/* dp[y1][x1][y2][x2] (x1<x2) = max{
a[y1][x1] + a[y2][x2] + max{dp[y1-1][x1][y2-1][x2], dp[y1][x1-1][y2][x2-1], dp[y1-1][x1][y2][x2-1], dp[y1][x1-1][y2-1][x2]}
}
*/
const int dir[2][2]={
{
1,0},{
0,1}};
int main()
{
// load data
int m,n;
while (2==scanf("%d%d",&m,&n))
{
static int a[51][51];
static int dp[51][51][51][51];
int x,y,num;
memset(a,0,sizeof(a));
memset(dp,-1,sizeof(dp));
for (int y=1;y<=m;y++)
for (int x=1;x<=n;x++)
scanf("%d",&a[y][x]);
// solve (dynamic planning)
dp