前提:在涉及“状态”,不是单单知道用dp,明白所定义的数组的意义,才是整个思路的核心。感性到理性过程。
题目链接:https://cn.vjudge.net/contest/313927#problem/D
翻译:
从(0,0)点出发,从一个点只能水平或竖直的到另一个点。并且下一个点的数值大于前一个点的数值这个点才能走,给你一个k,每次最多走k步,问所有能走的点的数值加起来最大是多少?
思路:从(0,0)点一直递归下去,一个点可能有多条路径,应该判断走哪条路径,能得到的值大?地图最大是100*100的,搜过的点可以保留下来。
dp[x][y]:从(x,y)出发,所能得到的最大值。
关于从一个点只能水平或竖直的到另一个点:
从A点一次只能到达它所在的竖行或橫行,不能到达B点,要到达B,分两次走。
从一个点到下一个点:
for(int i=0; i<4; i++)
for(int j=0; j<=k; j++) {
int tx=x+to[i][0]*j;
int ty=y+to[i][1]*j;
}
完整代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k;
int to[4][2]={-1,0,0,1,1,0,0,-1};
int mp[102][102];
int dp[100][100];
int dfs(int x,int y){
int ans=0;
if(dp[x][y])
return dp[x][y];
for(int i=0; i<4; i++){/*一个方向可以走1~k步*/
for(int j=0; j<=k; j++){
int tx=x+to[i][0]*j;
int ty=y+to[i][1]*j;
if(tx<0||tx>=n||ty<0||ty>=n||mp[tx][ty]<=mp[x][y])
continue;
ans=max(ans,dfs(tx,ty));
}
}
dp[x][y]=ans+mp[x][y];
return dp[x][y];
}
int main(){
while(~scanf("%d %d",&n,&k)){
if(n==-1&&k==-1)break;
memset(dp,0,sizeof(dp));
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
scanf("%d",&mp[i][j]);
dfs(0,0);
printf("%d\n",dp[0][0]);
}
return 0;
}