题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=61
分析: 一道双线程动态规划题,与第六届河南acm比赛的题类似.
题意:小纸条从(1,1)传到(m,n),再传回来,并且路线不能交叉,使好感度之和最高.我们可以认为是同时找出两条从(1,1)传到(m,n)的不相交的路线.
方法是:
计算每一步情况下的情况,一条道路用i,j控制,另一条用x,y控制.
从矩阵的角度看,k对应的是一条一条的斜线,值为横纵坐标之和,从3(1+2)开始,到m+n-2.i从1到m-1,对应的j为k-i,x从2到m,对应的y为k-j;
dp[k%2][i][x]中记录的是从(1,1)到(i,j),(x,y)两个点的最大好感度。a由计算得到,随横坐标变化。
状态转移为从需要计算的两点的(上,上),(上,左),(左,上),(左,左)方向的两点到(i,j),(x,y)的最大好感度+map[i][j]+map[x][y]。
代码为:
for(k=3;k<m+n;k++)
{
for(i=1,j=k-i;i<m;i++,j--)
{
if(j>n||j<=1)
continue;
for(x=i+1,y=k-x;x<=m;x++,y--)
{
if(y>=n||y<1)
continue;
dp[k%2][i][x]=map[i][j]+map[x][y];
tmp=(k-1)%2;
dp[k%2][i][x]+=max(max(dp[tmp][i-1][x-1],dp[tmp][i-1][x]),max(dp[tmp][i][x-1],dp[tmp][i][x]));
}
}
}
我的程序效率不是太高,看别人的博客说用网络流能更优化算法,可惜我不会网络流,要学的东西还很多。加油!!!
附上我的程序
#include <iostream>
#include <algorithm>
#include <cstring>
#define MAXN 61
using namespace std;
int main()
{
int T,m,n,i,j,k,x,y,tmp;
int map[MAXN][MAXN],dp[2][MAXN][MAXN];
cin>>T;
while(T--)
{
cin>>m>>n;
memset(dp,0,sizeof(dp));
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
cin>>map[i][j];
for(k=3;k<m+n;k++)
{
for(i=1,j=k-i;i<m;i++,j--)
{
if(j>n||j<=1)
continue;
for(x=i+1,y=k-x;x<=m;x++,y--)
{
if(y>=n||y<1)
continue;
dp[k%2][i][x]=map[i][j]+map[x][y];
tmp=(k-1)%2;
dp[k%2][i][x]+=max(max(dp[tmp][i-1][x-1],dp[tmp][i-1][x]),max(dp[tmp][i][x-1],dp[tmp][i][x]));
}
}
}
cout<<dp[(m+n-1)%2][m-1][m]<<endl;
}
return 0;
}