AcWing 1027. 方格取数

原题链接

考察: 线性dp

错误思路:

       先走一遍,将走过的地方mp标为0

这个算法本蒟蒻想不出来怎么实现....

正确思路:

       可以将两次走当作两次一起走.设第一次为A,第二次为B.只要步数相同,A和B的横纵坐标和就会相同.本来是需要4维数组,所以可以优化到三维.

       f[k][i][j]表示的就是到mp[i][k-i]和mp[j][k-j]的权值和.i就是A的横坐标,j是B的横坐标.那么如何进行集合划分呢.由摘花生那道题可以想出划分为四类: 1.A从上面来,B从上面来.2.A从左边来,B从上面来...以此类推.

注意: 上一层状态是k-1,不是k-2,k表示的是横纵坐标和

          最优解的两条路线一定没有交点.

自己简略的证明:

         f[4][2][2]的最值一定取自f[3][1][2]==f[3][2][1],如果mp[2][2]的值比mp[1][3]、mp[3][1]大,那么只走第2行的值一定比走1、2(或2,3)行小.因为f[4][2][3]和f[4][1][2]都能取到f[3][1][2]和mp[2][2],而i与j不同又能比f[4][2][2]多取一个值.以此类推后面的行

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

 

posted @ 2021-02-05 17:46  acmloser  阅读(64)  评论(0编辑  收藏  举报