极简的dp代码

xiaoxiao2021-02-27  511

设有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一定不要用递归。 另外,多维数组是可以用来保存状态的,而且很好用。

转载请注明原文地址: https://www.6miu.com/read-891.html

最新回复(0)