这题状态方程定义不难,难的是状态的转移,如果要在i~j之间设仓库,那么仓库一定是中间那个点,根据这个性质,先初始化1~i的设一个仓库的长度,然后从设2个仓库开始dp,转移方程为dp[i][j]=min(dp[i][j],dp[i-1][m]+cost[m][[j]),m的范围为i-1~j-1,代表1~m设立了1-i个点,然后在m~j设立了一个点,那么刚好可以转移。
//
// main.cpp
// Richard
//
// Created by 邵金杰 on 16/9/26.
// Copyright © 2016年 邵金杰. All rights reserved.
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200+10;
const int inf=99999999;
int p[maxn],dp[maxn][maxn],cost[maxn][maxn];
int abs(int x){ return x>0?x:-x;}
int main()
{
int n,k;
int kase=0;
while(scanf("%d%d",&n,&k))
{
if(n==0&&k==0) break;
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
memset(cost,0,sizeof(cost));
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
for(int m=i;m<=j;m++)
cost[i][j]+=abs(p[m]-p[(i+j)/2]);
for(int i=1;i<=n;i++) dp[1][i]=cost[1][i];
for(int i=2;i<=k;i++)
{
for(int j=i;j<=n;j++)
{
dp[i][j]=inf;
for(int m=i-1;m<=j-1;m++)
{
dp[i][j]=min(dp[i][j],dp[i-1][m]+cost[m+1][j]);
}
}
}
printf("Chain %d\n",++kase);
printf("Total distance sum = %d\n\n",dp[k][n]);
}
return 0;
}