矩阵类型DP

1、滑雪:从每个点开始枚举,记忆化搜索,记录dp[x][y]

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
int h[110][100];
int dp[110][110];
int r,c;
int dis[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int solve(int x,int y){
	if(x<1||x>r||y<1||y>c) return 0;
	if(dp[x][y]!=0) return dp[x][y];
	dp[x][y]=1; //本身的高度别忘了 
	for(int i=0;i<4;i++){
		int xx=x+dis[i][0],yy=y+dis[i][1];
		if(h[xx][yy]>h[x][y]) dp[x][y]=max(dp[x][y],solve(xx,yy)+1);
}
	return dp[x][y];
}
int main(){
	scanf("%d %d",&r,&c);
	for(int i=1;i<=r;i++)
	for(int j=1;j<=c;j++) scanf("%d",&h[i][j]);
	int ans=0;
	for(int i=1;i<=r;i++)
	for(int j=1;j<=c;j++) {
		ans=max(ans,solve(i,j));
	}
	printf("%d",ans);
return 0;
}  

2、传纸条

4维----3维

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
int a[51][51];
int f[110][51][51]; //第一位要扩大1倍 
int n,m; 
/*
第二种做法为三维dp,如果这道题数据被加强了一点,那就应该用这个方法。
仔细观察,我们不难发现一个规律,对于每次转移,这两位同学的纸条走的步数总是相等的,也就是应该总有i+j = k+l = step,我们从这里考虑入手,简化一下那个方程。
我们枚举走的步数,同时枚举第一个人和第二个人的横坐标或者纵坐标,对,只枚举一个就好,另一个可以算出来。
我枚举的是横坐标。
但这样做第一维(也就是枚举步数那一维)要开两倍大小(步数最大有n+m-1),并且需要加入判断重合操作。
优化之后速度比上一个快很多,它的时间复杂度是O(n^2*(n+m)).
*/
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
	}
	for(int step=1;step<n+m;step++){
		for(int i=1;i<=n;i++){
			for(int x=1;x<=n;x++){
				int j=step-i+1;
				int y=step-x+1;
				if(j<1||y<1) continue;
				f[step][i][x]=max(max(f[step-1][i-1][x-1],f[step-1][i][x]),max(f[step-1][i-1][x],f[step-1][i][x-1]))+a[i][j]+a[x][y];
				if(i==x) f[step][i][x]-=a[i][j];
			}
		}
	}
	printf("%d
",f[n+m-1][n][n]);
return 0;
}

  

原文地址:https://www.cnblogs.com/shirlybaby/p/12296301.html