CodeForces - 321E:Ciel and Gondolas (四边形不等式优化DP)

题意:N个人排成一行,分成K组,要求每组的不和谐值之和最小。

思路:开始以为是斜率优化DP,但是每个区间的值其实已经知道了,即是没有和下标有关的未知数了,所以没必要用斜率。 四边形优化。

dp[i][j]表示前j个人分为i组的最小代价。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=4010;
int sum[maxn][maxn],cost[maxn][maxn],dp[810][maxn],pos[810][maxn];
void read(int &x){
    x=0; char c=getchar();
    while(c>'9'||c<'0') c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
}
int main()
{
    int N,K,x,y;
    scanf("%d%d",&N,&K);
    rep(i,0,K) rep(j,0,N) dp[i][j]=2000000000;
    rep(i,1,N) rep(j,1,N){
        read(sum[i][j]);
        sum[i][j]=sum[i][j]+sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
    }
    rep(i,1,N) rep(j,i+1,N) cost[i][j]=(sum[j][j]+sum[i-1][i-1]-sum[j][i-1]-sum[i-1][j])/2;
    rep(i,1,N) dp[1][i]=cost[1][i];
    rep(i,2,K){
       for(int j=N;j>=i;j--){
         int L=pos[i-1][j]?pos[i-1][j]:1;
         int R=pos[i][j+1]?pos[i][j+1]:N;
         rep(k,L,R){
            if(dp[i-1][k]+cost[k+1][j]<dp[i][j]){
                dp[i][j]=dp[i-1][k]+cost[k+1][j];
                pos[i][j]=k;
            }
         }
       }
    }
    printf("%d\n",dp[K][N]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/9941633.html