ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOIP 2000 方格取数 dp

2021-07-06 20:34:08  阅读:152  来源: 互联网

标签:路径 i1 i2 取数 int 2000 当前 dp


题目链接

题意:
有n*n的方格,有些格子上有数,有些格子上没有数(可以认为是0),现从(1,1)走到(n,n)走两次,走过之后,上面的数就会变为0,问两次走的路径取得的数字之和最大为多少?

思路:
状态表示:
d p [ i 1 ] [ i 2 ] [ k ] dp[i1][i2][k] dp[i1][i2][k]表示从(1,1)开始两条路径分别走到 ( i 1 , k − i 1 ) , ( i 2 , k − i 2 ) (i1,k-i1),(i2,k-i2) (i1,k−i1),(i2,k−i2)取得的数字的最大值。

其实 k = i 1 + j 1 = i 2 + j 2 k=i1+j1=i2+j2 k=i1+j1=i2+j2,我们让两个路径的横纵坐标加和相同,可以理解为步长(但不是步长),步长相同刚好能枚举在同一时刻的状态,因为他们走的步数一样嘛。
有步长了,就可以根据横坐标推出纵坐标了。所以就很巧妙

当前状态可由四种情况来转移:

上一个状态都是步长减一,表示的是两条路径步长都减去一,两条路径是同时进行的。

  • d p [ i 1 − 1 ] [ i 1 − 1 ] [ k − 1 ] dp[i1-1][i1-1][k-1] dp[i1−1][i1−1][k−1]表示两条路径都是从当前点的上方转移而来的,当前点指的是两条路径分别对应的当前点,不一定一样
  • d p [ i 1 − 1 ] [ i 2 ] [ k − 1 ] dp[i1-1][i2][k-1] dp[i1−1][i2][k−1]表示第一条路径从当前点(第一条路径的当前点)的上方转移而来的,第二条路径从当前点(第二条路径的当前点)的左边转移而来
  • d p [ i 1 ] [ i 2 − 1 ] [ k − 1 ] dp[i1][i2-1][k-1] dp[i1][i2−1][k−1]表示第一条路径从当前点(第一条路径的当前点)的左边转移而来的,第二条路径从当前点(第二条路径的当前点)的上方转移而来
  • d p [ i 1 ] [ i 2 ] [ k − 1 ] dp[i1][i2][k-1] dp[i1][i2][k−1]表示两条路径都是从当前点的左边转移而来的,当前点指的是两条路径分别对应的当前点,不一定一样

状态来自这四种情况

所以只要取他们的最大值就行了

注意:
都是从上方或者左边转移的,他们不一定来自同一个点,所以只有 i 1 = i 2 i1=i2 i1=i2时,他们才来自同一个点,这时候,取的数就会只有一个,因为一条路径取过之后方格上的数就会变为0

#include<bits/stdc++.h>
using namespace std;
int a[15][15],dp[15][15][30];

int main()
{
    int n;cin>>n;
    int x,y,num;
    //都为0时才结束
    while(cin>>x>>y>>num,x||y||num)
        a[x][y]=num;
    for(int k=2;k<=n+n;k++)//k=i1+j1=i2+j2
    {
        for(int i1=1;i1<=n;i1++)
        {
            for(int i2=1;i2<=n;i2++)
            {
                int j1=k-i1,j2=k-i2;
                if(j1>=1&&j1<=n&&j2>=1&&j2<=n)//纵坐标必须满足条件
                {
                    int w = a[i1][j1];
                    if(i1!=i2) w+=a[i2][j2];//不是同一个点就加两个方格对应的数
                    int &q = dp[i1][i2][k];//太长了,用引用减少代码量
                    q=max(q,dp[i1-1][i2-1][k-1]+w);
                    q=max(q,dp[i1-1][i2][k-1]+w);
                    q=max(q,dp[i1][i2-1][k-1]+w);
                    q=max(q,dp[i1][i2][k-1]+w);
                }
            }
        }
    }
    cout<<dp[n][n][n+n]<<'\n';
    return 0;
}

标签:路径,i1,i2,取数,int,2000,当前,dp
来源: https://blog.csdn.net/qq_50285142/article/details/118528294

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有