寒假集训专题二 K.方格取数
题意:
给一个n*n的方格,从(1,1)到(n,n),走两次,只能往右或往下,求取得的路径数字和的最大值
思路:
首先想用两次二维的DP解决,发现两个问题
1.求路径的时候把数字化为0不好判断,从终点到起点每次出最大值返回上一个位置存在上一个位置的dp值相同的情况,给解题带来不便。
2.会存在
0 0 2 3 0 0 0
0 0 3 0 0 0 0
0 0 3 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 4 0 0
0 0 0 0 4 0 0
0 0 3 0 4 0 0
0 0 3 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 3 0 0 0
可见这两个三在第二次dp中无论如何都无法被算入总情况
两次dp的做法类似贪心,求出局部最优解,但不是整体最优解!
所以我们采用一次性走两次的做法,开四维数组
#include
const int N=11;
int dp[N][N][N][N];
int a[N][N];
using namespace std;
typedef pair PII;
vector< PII > ve;
signed main()
{
int n;
cin>>n;
int x,y,z;
while(~scanf("%d",&x))
{
if(x==0) break;
scanf("%d%d",&y,&z);
a[x][y]=z;
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
for(int l=1;l<=n;l++)
{
dp[i][j][k][l]=a[i][j]+a[k][l]+max(max(dp[i-1][j][k-1][l],dp[i-1][j][k][l-1]),max(dp[i][j-1][k-1][l],dp[i][j-1][k][l-1]));
//这里有些吃力,可以这样想,(i,j)(k,l)一定取前一种情况即(i-1,j)(i,j-1)(k-1,l)(k,l-1)所以算起来一共是4种
if(i==k&&j==l) //若两个点重复了,则减去,不影响最后的答案
{
dp[i][j][k][l]-=a[i][j];
}
}
}
}
}
cout<
其他解法
网络流
[P1004 NOIP2000 提高组] 方格取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)