luogu 1006 1004 传纸条 方格取数

xiaoxiao2025-04-19  40

传纸条:https://www.luogu.org/problemnew/show/P1006

方格取数:https://www.luogu.org/problemnew/show/P1004

 

这两道题一样的……所以我放在一起整理

方格取数比较简单,记住一条公式,方格任意一点:i+j=k+2。对于这道题,因为开始从左上角走,所以k是走的步数,所以我们只需要一个三维dp,f[k][i][j]表示走了k步,第一个人在第i列,第二个人在第j列,然后根据公式,横坐标也推出来了,所以复杂度只是三次方!然后对于取完数变0这个操作,只需要当横纵坐标都相等时,只取一个就行了。

 

#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> int a[15][15],f[15<<1][15][15],n; using namespace std; int main() { cin>>n; int x,y,z; while(scanf("%d %d %d",&x,&y,&z)) { if(x==0&&y==0&&z==0)break; a[x][y]=z; } f[0][1][1]=a[1][1]; for(int k=1;k<=2*n-2;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int x=k+2-i,y=k+2-j; if(x<1||j<1)continue;//判越界 f[k][i][j]=max(f[k-1][i][j],max(f[k-1][i-1][j],max(f[k-1][i][j-1],f[k-1][i-1][j-1])))+a[i][x]+a[j][y]; if(i==j&&x==y)f[k][i][j]-=a[i][x]; } } } cout<<f[2*n-2][n][n]; }

传纸条代码其实差不多的,基本思路也就像上面那个一样。但是它多了一个条件,就是走过了一个格子,另一个人是不能再走的,相当于封路了。这个时候我们要把列强制不相等吗?其实不是的,像上面那样,走到一起就减去就好了。为什么可以这样呢?

 

https://www.luogu.org/discuss/show?postid=63900

 

引用了luogu的xeonz1的讨论发言

 

#include <iostream> #include <cstring> #include <cstdio> #define maxn 55 using namespace std; int f[2 * maxn][maxn][maxn]; int a[maxn][maxn]; int n,m; int max_ele(int a,int b,int c,int d){ if (b>a) a = b; if (c>a) a = c; if (d>a) a = d; return a; } int main(){ cin >> n >> m; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) cin >> a[i][j]; for (int k=1;k<=n+m-1;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++){ int xx=k-i+2,yy=k-j+2; if (k-i+2<1 || k-j+2<1) //这里是判断纵坐标的合法性,如果纵坐标不合法那就跳过去 continue; f[k][i][j] = max_ele(f[k-1][i][j],f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j]) + a[i][xx] + a[j][yy]; if (i==j&&xx==yy) //判断重合路径 f[k][i][j]-=a[i][xx]; } cout << f[n+m-2][n][n] << endl; return 0; }

 

转载请注明原文地址: https://www.6miu.com/read-5028658.html

最新回复(0)