简单DP
因为一定是小的数字推到大的数字,所以排序,转化成线性的DP
#include<cstdio> #include<cstring> #include<cmath> #include<stack> #include<vector> #include<string> #include<iostream> #include<algorithm> using namespace std; const int maxn=100+10; int a[maxn][maxn],b[maxn][maxn]; int n,k; struct X { int r,c; int val; } s[maxn*maxn]; int dp[maxn*maxn]; bool cmp(const X&a,const X&b) { return a.val<b.val; } int main() { while(~scanf("%d%d",&n,&k)) { if(n==-1&&k==-1) break; for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { s[i*n+j].r=i; s[i*n+j].c=j; scanf("%d",&s[i*n+j].val); a[i][j]=s[i*n+j].val; } } sort(s,s+n*n,cmp); for(int i=0;i<n*n;i++) b[s[i].r][s[i].c]=i; for(int i=0;i<n*n;i++) dp[i]=-1; int pos; for(int i=0;i<n*n;i++) if(s[i].r==0&&s[i].c==0) {pos=i;break;} dp[pos]=s[pos].val; int ans=dp[pos]; for(int i=pos;i<n*n;i++) { if(dp[i]==-1) continue; int R=s[i].r; int C=s[i].c; for(int j=R-k;j<=R+k;j++) { if(j<0||j>=n) continue; if(a[j][C]<=a[R][C]) continue; if(dp[i]+a[j][C]>dp[b[j][C]]) { dp[b[j][C]]=dp[i]+a[j][C]; ans=max(ans,dp[b[j][C]]); } } for(int j=C-k;j<=C+k;j++) { if(j<0||j>=n) continue; if(a[R][j]<=a[R][C]) continue; if(dp[i]+a[R][j]>dp[b[R][j]]) { dp[b[R][j]]=dp[i]+a[R][j]; ans=max(ans,dp[b[R][j]]); } } } printf("%d ",ans); } return 0; }