E02 线性DP 数字三角形

视频链接:E02 线性DP 数字三角形_哔哩哔哩_bilibili

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 @   董晓  阅读(571)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示