nyoj-传纸条(一)

                                            NYOJ-----------传纸条(一)

这题是一道动规题目,原本打算在原矩阵上动手脚(预处理)
发现预处理只能找一条路的最大值!
于是,如何判重就非常重要了!
于是绞尽脑汁!!!!!!!!!
如果做标记的话预处理就没有用了!


换一个思路:
题目求来回两条路的最大值,然而发现去的路反过来也可以当回来的路
意思就是选中一条路,既可以当回去的路,也可以当去的路
那么我从起点出发,找到两条到终点的路,让两条路的值最大
联系动规的特点:
对于每一个状态把所有的下一个状态可能的情况都列出来,取最优解
对于这道题,有四种状态
所以状态转移方程为
dp[x1][y1][x2][y2]=max(dp[x1][y1][x2][y2],dp[x1][y1][x2][y2],dp[x1][y1][x2][y2],dp[x1][y1][x2][y2])+map[x1][y1]+map[x2][y2]  其中(x1!=x2&&y1!=y2)
仔细分析一下状态转移方程
其实就是把每个点都根据上个点可能的值找最优解
但是这个状态转移方程是有问题的!!!
在题目中,必须保证两条路的进度一样,就是第一条路走几步,第二条路就走几步
所以我认为光凭上面的状态转移方程是没办法解出这道题的
那么,就需要找一个东西来表示走的步数
发现每走一步,x和y只能选一个进行加1(以1,1为起点)
即x+y-2表示走的步数  比如 (1,2)  1+2-2=1
表示从(1,1)走一步就可以到(1,2)    
每次更新点的时候找这些点就可以了
还有一个问题为数组开的太大了!!!
简直爆炸!
那么怎么缩减?如果我记录步数K,那么我就可以用K和x1,x2推出y1,y2减少了一维
而且我这样用K记录步数更容易对更新的点进行操控!!!(具体看代码)
下面上代码:(完整状态转移方程在代码中)
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int max4(int a,int b,int c,int d)
{
    return max(max(a,b),max(c,d));
}
int map[55][55];
int map0[110][55][55];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(map,0,sizeof(0));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&map[i][j]);
            }
        }
        memset(map0,0,sizeof(map0));
        map0[2][1][1]=map[1][1];
        for(int k=2;k<=m+n;k++)//k-2表示步数,但是因为走0步其x+y为1,所以就这样调整
        {
            for(int x1=1;x1<=n;x1++)//两层循环遍历所有点
            {
                for(int x2=1;x2<=n;x2++)
                {
                    int y1=k-x1;
                    int y2=k-x2;
                    if(y1<1||y2<1||y1>m||y2>m||y1==y2||x1==x2)//如果点出界直接跳过
                    {
                        continue;
                    }
                    map0[k][x1][x2]=max4(map0[k-1][x1-1][x2],map0[k-1][x1][x2-1],map0[k-1][x1-1][x2-1],map0[k-1][x1][x2])+map[x1][y1]+map[x2][y2];//状态转移方程
                }
            }
        }
        printf("%d\n",map0[m+n-1][n][n-1]);//此处重点难点!!!
    }
}

重难点讲解:
map0[m+n-1][n][n-1]表示到最后一个点的前一步,m+n-1很好理解
但是为什么是n 和n-1?   因为首先这表示的是x1和x2
而其范围都是n,所以都和n有关
其次为什么是n-1?
因为其必定是x1在下方,x2在上方!!!
而其如果走最后一步,x1必定是向右走,x2是向下走!!












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值