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; }