luoguP1004 方格取数(四维DP)

题目链接:https://www.luogu.org/problemnew/show/P1004

思路:

  这道题是四维DP的模板题,与luoguP1006传纸条基本相似,用f[i][j][k][l]表示第一个人走到(i,j),第二个人走到(k,l)时两个人取得数的和的最大值。显然复杂度最多为9×9×9×9=6561,所以这个方法可行。

  状态转移方程为:f[i][j][k][l]=max(f[i][j-1][k][l-1],max(f[i][j-1][k-1][l],max(f[i-1][j][k][l-1],f[i-1][j][k-1][l])))+a[i][j]+a[k][l];
  其中需要注意(i,j)与(k,l)重合的情况。

AC代码如下:

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4
 5 int n;
 6 int a[12][12],f[12][12][12][12];
 7
 8 int main(){
 9     scanf("%d",&n);
10     int r,c,val;
11     while(scanf("%d%d%d",&r,&c,&val)!=EOF&&r)
12         a[r][c]=val;
13     for(int i=1;i<=n;i++)
14         for(int j=1;j<=n;j++)
15             for(int k=1;k<=n;k++)
16                 for(int l=1;l<=n;l++){
17                     f[i][j][k][l]=max(f[i][j-1][k][l-1],max(f[i][j-1][k-1][l],max(f[i-1][j][k][l-1],f[i-1][j][k-1][l])))+a[i][j]+a[k][l];
18                     if(i==k&&j==l)
19                         f[i][j][k][l]-=a[i][j];
20                 }
21     printf("%d\n",f[n][n][n][n]);
22     return 0;
23 }

原文地址:https://www.cnblogs.com/FrankChen831X/p/10329971.html

时间: 2024-11-15 18:19:56

luoguP1004 方格取数(四维DP)的相关文章

方格取数(DP)(NOIP2000)

不要多想,我不是无聊到刷NOIP2000的题目,只是老师用考试告诉我们,我们的DP很弱,so咱家来找道DP提做 还有,这个题貌似和矩阵取数那个没有什么关系 题目简述:给你一个N*N的方格(小的很,N只有10),你可以向右或向下走一步,并取走其中的数字,你要取两次,输出最后取数的和 首先,这是一个棋盘DP,我们从左上到右下DP就好了,我一开始打的是记录位置的方法,跑两次DP,然而坑了,那我们要在仔细分析一下问题,N很小,小到你能开到6维不会爆内存,所以大胆的去提高维度吧,在分析问题,其实我们要找的

方格取数(DP)

描述 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点.在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0). 此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大. 输入 输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数.一行单独的0表示输入结束. 输

HDU - 1565 方格取数(1) (DP)

Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20) Output 对于每个测试实例,输出可能取得的最大的和 Sample Input 3 75 15 21 75 15 28 34 70 5 Sample Output 188 思路:用dp[i][j]表示到i行时下

【noi 2.6_8786】方格取数(DP+优化)

题意:N*N的方格图每格有一个数值,要求从左上角每步往右或往下走到右下角,问走2次的最大和. 解法:走一次的很好想,而走2次,不可误以为先找到最大和的路,再找剩下的最大和的路就是正解.而应该认清动态规划的实质,定义为最佳解的状态,因此要走的2次都要涵括. O(n^4)——f[i][j][k][l]表示分别走到(i,j)和(k,l)的最大和.每次从上一步分别走(下,下),(右,右),(右,下),(下,右)的状态推导就好了.f[i][j][k][l]=max(f[i-1][j][k-1][l],f[

方格取数(普通dp)

设dp[i][j][l][k]表示走第一个走到i,j,第二个走到l,k,的最大值 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; int dp[11][11][11][11]; int a[100][100]; int main(){ int n; int x,y,z; cin>>n>>x>

neu1458 方格取数 dp解法

题意: 有N * N个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),把所有经过的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次. 走两次,所以状态表示要同时表示两次路径.dp[i][j][k][l] 表示第一次走到i,  j,第二次走到k, l得到的最大值,这里i + j == k + l 其实第四维是可以通过前三维算出来的,所以可以去掉 那么dp[i][j][k] 可以通过四种状

HDU 1565 方格取数(1) (状态压缩 DP)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5779    Accepted Submission(s): 2194 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

HDU 1565 方格取数(1)(状压dp)

感觉这道题目的数据比较水啊,程序的时间复杂度为1711^2*20竟然也可以过掉....其他的就是状压了啊,注意需要滚动一下啊.... 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5701    Accepted Submission(s): 2159 Problem Description 给你一个n*n的格子的棋

HDU 1565&amp;1569 方格取数系列(状压DP或者最大流)

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6206    Accepted Submission(s): 1975 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的