E02 方格DP 数字三角形

视频链接:https://www.bilibili.com/video/BV1Rk4y1173p/

Luogu P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=1005;
int n,a[N][N],f[N][N];

int main(){
  scanf("%d",&n);
  for(int i=1; i<=n; i++)
    for(int j=1; j<=i; j++)
      scanf("%d",&a[i][j]);
    
  for(int i=n; i>=1; i--)
    for(int j=1; j<=i; j++)
      f[i][j]=max(f[i+1][j],f[i+1][j+1])+a[i][j];
    
  printf("%d\n",f[1][1]);
}

Luogu P1004 [NOIP2000 提高组] 方格取数

思路:
等价于两人同时走,并且走相同步数。条件:i+j == x+y
f[i,j,x,y]表示同时分别从(1,1)(1,1)走到(i,j)(x,y)的路径,取数的最大值

两点(i,j)(x,y)的上一步可能是:
上,上:(i-1,j)(x-1,y);
上,左:(i-1,j)(x,y-1);
左,上:(i,j-1)(x-1,y);
左,左:(i,j-1)(x,y-1);
f[i,j,x,y] = max(....)

当i == x && j == y时代表两条路径出现重复点,则只取一次a[i][j]的值

#include <iostream>
using namespace std;

const int N=11;
int a[N][N];
int f[N][N][N][N];

int main(){
  int n, x, y;
  cin>>n;  
  while(cin>>x>>y>>a[x][y], x);
  
  for(int i=1; i<=n; i++)
  for(int j=1; j<=n; j++)
  for(int x=1; x<=n; x++)
  for(int y=1; y<=n; y++)
    if(i+j==x+y){
      int &t=f[i][j][x][y];
      t=max(max(f[i-1][j][x-1][y], f[i-1][j][x][y-1]),
            max(f[i][j-1][x-1][y], f[i][j-1][x][y-1]));
      if(i==x && j==y) t+=a[i][j]; //走到同一点
      else t+=a[i][j]+a[x][y];
    }
    
  cout<<f[n][n][n][n];
}
// 利用约束条件,降维优化,令 i+j=x+y=k 表示走的步数
// f[k,i,x]表示共走了k步,两人分别走到i行x行,取数的最大值
#include <iostream>
#include <algorithm>
using namespace std;

const int N=11;
int a[N][N];
int f[N+N][N][N];

int main(){
  int n, x, y;
  cin>>n;
  while(cin>>x>>y>>a[x][y], x);
  
  for(int k=2; k<=n+n; k++)     //走了k步
    for(int i=1; i<=n; i++)     //走到i行
      for(int x=1; x<=n; x++){  //走到x行
        int j=k-i, y=k-x;
        if(j>=1&&j<=n&&y>=1&&y<=n){
          int &t=f[k][i][x];
          t=max(max(f[k-1][i-1][x-1],f[k-1][i-1][x]),
                max(f[k-1][i][x-1], f[k-1][i][x]));
          if(i==x) t+=a[i][j];
          else t+=a[i][j]+a[x][y];
        }
      }
  cout<<f[n+n][n][n];
}

Luogu P1006 [NOIP2008 提高组] 传纸条

#include <iostream>
#include <algorithm>
using namespace std;

const int N=55;
int a[N][N];
int f[N+N][N][N];

int main(){
  int m,n; cin>>m>>n;
  for(int i=1; i<=m; i++)
    for(int j=1; j<=n; j++)cin>>a[i][j];
  
  for(int k=2; k<=m+n; k++) //步数
  for(int i=1; i<=m; i++)   //
  for(int x=1; x<=m; x++){  //
    int j=k-i, y=k-x;
    if(j<1 || j>n || y<1 || y>n) continue;
    int &t=f[k][i][x];
    t=max(max(f[k-1][i-1][x-1],f[k-1][i-1][x]), 
          max(f[k-1][i][x-1], f[k-1][i][x]));
    if(i==x) t+=a[i][j]; 
    else t+=a[i][j]+a[x][y]; 
  }
  
  cout<<f[m+n][m][m];
}

 

posted @ 2023-04-09 18:45  董晓  阅读(451)  评论(0编辑  收藏  举报