题目链接在这里:D - National Railway (atcoder.jp)
首先需要明确的是在地图上选择两点,两点的位置关系有两种,一种是左上右下,一种是左下右上!!!
然后这是一种比较经典的操作吧,就是维护一个二维的前缀最小值,注意由于位置关系有两种,所以维护的最小值也是有两种,一种是左对角线,一种是右对角线
1 #include "bits/stdc++.h" 2 using namespace std; 3 const int MAX=1005; 4 typedef long long LL; 5 LL n,m,c,ans; 6 LL a[MAX][MAX],d[MAX][MAX],b[MAX][MAX]; 7 int main(){ 8 freopen ("d.in","r",stdin); 9 freopen ("d.out","w",stdout); 10 int i,j,k,w; 11 scanf("%lld%lld%lld",&n,&m,&c); 12 for (i=1;i<=n;i++) for (j=1;j<=m;j++) scanf("%lld",&a[i][j]); 13 b[1][1]=9000000000000000000ll;d[1][1]=a[1][1]-c*2; 14 for (i=2;i<=n;i++) b[i][1]=min(b[i-1][1],a[i-1][1]-c*i),d[i][1]=a[i][1]-c*(i+1); 15 for (i=2;i<=m;i++) b[1][i]=min(b[1][i-1],a[1][i-1]-c*i),d[1][i]=a[1][i]-c*(i+1); 16 for (i=2;i<=n;i++){ 17 for (j=2;j<=m;j++){ 18 d[i][j]=a[i][j]-c*(i+j); 19 b[i][j]=min(b[i-1][j],min(b[i][j-1],min(d[i-1][j],d[i][j-1]))); 20 } 21 } 22 ans=9000000000000000000ll; 23 for (i=1;i<=n;i++){ 24 for (j=1;j<=m;j++){ 25 if (i==1 && j==1) continue; 26 ans=min(ans,b[i][j]+a[i][j]+c*(i+j)); 27 } 28 } 29 for (i=1;i<=n;i++) for (j=1;j<=m/2;j++) swap(a[i][j],a[i][m-j+1]); 30 memset(b,0,sizeof(b)); 31 b[1][1]=9000000000000000000ll;d[1][1]=a[1][1]-c*2; 32 for (i=2;i<=n;i++) b[i][1]=min(b[i-1][1],a[i-1][1]-c*i),d[i][1]=a[i][1]-c*(i+1); 33 for (i=2;i<=m;i++) b[1][i]=min(b[1][i-1],a[1][i-1]-c*i),d[1][i]=a[1][i]-c*(i+1); 34 for (i=2;i<=n;i++){ 35 for (j=2;j<=m;j++){ 36 d[i][j]=a[i][j]-c*(i+j); 37 b[i][j]=min(b[i-1][j],min(b[i][j-1],min(d[i-1][j],d[i][j-1]))); 38 } 39 } 40 for (i=1;i<=n;i++){ 41 for (j=1;j<=m;j++){ 42 if (i==1 && j==1) continue; 43 ans=min(ans,b[i][j]+a[i][j]+c*(i+j)); 44 } 45 } 46 printf("%lld",ans); 47 return 0; 48 }