HihoCoder - 1617

题意:

给定一个NxN的方格矩阵,每个格子中都有一个整数Aij。小Hi和小Ho各自选择一条从左上角格子到右下角格子的路径,要求路径中每一步只能向右或向下移动,并且两条路径不能相交(除了左上右下起止方格)。  

现在将两条路径经过的整数加起来求和。你能计算出这个和最大是多少吗?

思路:dp;2*n步俩个人都做完,所以一维是步数每次缺上一步最优来更新当前这步;第二维是第一个人走了多少横坐标方向的,由步数减横坐标,纵坐标就能知道了;同理第三维是第二个人的横坐标走的步数;

因为不能交叉,在横坐标数相同时(当前所在位置必定重合),把dp只更新一次(不同的更新是有两个点的值的),所以除了首位重合外,其他点重合必定不是最优(都是正数);

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define sfi(i) scanf("%d",&i)
#define pri(i) printf("%d\n",i)
#define sff(i) scanf("%lf",&i)
#define ll long long
#define mem(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define eps 1e-6
#define PI acos(-1)
#define lowbit(x) ((x)&(-x))
#define zero(x) (((x)>0?(x):-(x))
inline void sc(T &ret)
{
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}

int dp[205*2][209][209];
int a[209][209];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++) cin>>a[i][j];
    }
    mem(dp,0);
    for(int cnt=1;cnt<=2*n;cnt++)
    {
        for(int i=1;i<=cnt&&i<=n;i++)
        {
            for(int j=1;j<=cnt&&j<=n;j++)
            {
                int Max=-INF;
                Max=max(dp[cnt-1][i][j],Max);
                Max=max(dp[cnt-1][i-1][j],Max);
                Max=max(dp[cnt-1][i][j-1],Max);
                Max=max(dp[cnt-1][i-1][j-1],Max);
                if(i==j) dp[cnt][i][j]=Max+a[cnt-i+1][i];
                else dp[cnt][i][j]=Max+(a[cnt-i+1][i]+a[cnt-j+1][j]);
            }
        }
    }
    cout<

 

你可能感兴趣的:(dp)