OI Problems   关于

题解

TODO

时间复杂度 Θ(n)\Theta(n)

  代码
// 2023.09.04

#include<bits/stdc++.h>
using namespace std;

int n,a[2005][2005],c[2005][2005];
long long sum[5][2005][2005],dp[5][2005][2005];
// dp[k][i][j]: 表示在矩形的角 k 上到 i 行 j 列为止的最小花费
// k = 1(左上), 2(右上), 3(左下), 4(右下)

long long getsum(int k,int x1,int y1,int x2,int y2){
    return sum[k][x2][y2]-sum[k][x1-1][y2]-sum[k][x2][y1-1]+sum[k][x1-1][y1-1];
}

int main(){
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&c[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            scanf("%d",&a[i][j]);
            for(int k=1;k<=4;k++)
                sum[k][i][j]=sum[k][i-1][j]+sum[k][i][j-1]-sum[k][i-1][j-1]+a[i][j];
            sum[c[i][j]][i][j]-=a[i][j];
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            dp[1][i][j]=min(dp[1][i-1][j]+getsum(4,i,1,i,j),dp[1][i][j-1]+getsum(1,1,j,i,j));
    for(int i=1;i<=n;i++)
        for(int j=n;j>=1;j--)
            dp[2][i][j]=min(dp[2][i-1][j]+getsum(2,i,j,i,n),dp[2][i][j+1]+getsum(1,1,j,i,j));
    for(int i=n;i>=1;i--)
        for(int j=1;j<=n;j++)
            dp[3][i][j]=min(dp[3][i+1][j]+getsum(4,i,1,i,j),dp[3][i][j-1]+getsum(3,i,j,n,j));
    for(int i=n;i>=1;i--)
        for(int j=n;j>=1;j--)
            dp[4][i][j]=min(dp[4][i+1][j]+getsum(2,i,j,i,n),dp[4][i][j+1]+getsum(3,i,j,n,j));
    long long answer=0x7fffffffffffffff;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            answer=min(answer,dp[1][i][j]+dp[2][i][j+1]+dp[3][i+1][j]+dp[4][i+1][j+1]);
    printf("%lld\n",answer);
    return 0;
}