极简的dp代码

来源:互联网 发布:plsql打开sql文件乱码 编辑:程序博客网 时间:2024/06/01 15:32

设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):

某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。

此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。

输入描述 Input Description

输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
输出描述 Output Description

只需输出一个整数,表示2条路径上取得的最大的和。

样例输入 Sample Input

  8  2  3  13  2  6   6  3  5   7  4  4  14  5  2  21  5  6   4  6 3  15  7 2  14  0 0  0

样例输出 Sample Output

  67

数据范围及提示 Data Size & Hint
如描述

作为一道比较简单的dp题,只要列好状态方程然后就可以求解了。
于是第一遍我就傻乎乎的直接写了,直到看到了下面那段极简轻奢的代码

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int n,x,y,v;int f[11][11][11][11];//用于记录经由x1,y1,x2,y2,到达该点的最大取值int a[11][11];//很简单的保存一下地图int main(){    scanf("%d",&n);    while (true)    {        scanf("%d%d%d",&x,&y,&v);        if(x==0)   break;        a[x][y]=v;    }//输入,很简单,不解释    for(int x1=1;x1<=n;x1++)      for(int y1=1;y1<=n;y1++)         for(int x2=1;x2<=n;x2++)            for(int y2=1;y2<=n;y2++)//由于本题数据比较小,可以允许如此暴力的进行枚举               {                   f[x1][y1][x2][y2]=max(max(f[x1-1][y1][x2-1][y2],f[x1-1][y1][x2][y2-1]),max(f[x1][y1-1][x2-1][y2],f[x1][y1-1][x2][y2-1]))+a[x1][y1]+a[x2][y2];                   //重点来了,先取路径1从左边来时,路径2从左边来和从上边来的较大值,同时也取路径1从上边来,路径2从左边和上边两种情况下的最大值,接着再取最大值                  //等于得到了到达这一步前可能取得的最大值,然后加上这一点的权值,即为这一点的最大取值                   if(x1==x2&&y1==y2)                    //x1,y1控制前一条路径  x2,y2控制后一条路径                     f[x1][y1][x2][y2]-=a[x1][y1];//若两条路径的数值相同,说明其为同一条路径,其数值只能加一遍,然而前面两条路径相同时,并没有考虑取完之后该方格为空,所以要额外减去               }//输出两条路径的和    int ans=f[n][n][n][n];//输出不解释    printf("%d",ans);    return 0;}

题目很简单,但是能写到如此精简,也是不易。
提醒我,能用循环写的dp一定不要用递归。
另外,多维数组是可以用来保存状态的,而且很好用。

0 0
原创粉丝点击