经典的DP,用dp[i][j] 表示前j个餐馆建i个仓库 dp[i][j] = min (dp[i-1][k] , cost[k+1][j])(i – 1<= k < j);表示在前k个餐馆建i-1个仓库的前提下,把第i的仓库建在k+1 到j 的餐馆之间,这样就能保证最优!其中cost[][] 可以通过预处理得出,如果i 到j之间要建仓库那么必定会建在下标为(i+j)/2的餐馆!dp的初始值要仔细!
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
int main(){
int n, k, dp[35][205], T = 1, cost[205][205], a[205], Case = 1;
while( scanf( "%d%d", &n, &k ) && !( n == 0 && k == 0 ) ){
memset( dp, 0, sizeof( dp ) );
memset( cost, 0, sizeof( cost ) );
memset( a, 0, sizeof( a ) );
for( int i = 1; i <= n; i++ ){
cin >> a[i];
}
for( int i = 1; i <= n; i++ ){
for( int j = i; j <= n; j++ ){
cost[i][j] = 0;
for( int k = i; k <= j; k++ ){
cost[i][j] += abs( a[k] - a[(i+j)/2] );
}
}
}
for( int i = 2; i <= n; i++ ){
dp[1][i] = cost[1][i];
}
for( int i = 2; i <= k; i++ ){
for( int j = i + 1; j <= n; j++ ){
int min = 9999999;
for( int m = i - 1; m < j; m++ ){
if( dp[i-1][m] + cost[m+1][j] < min ){
min = dp[i-1][m] + cost[m+1][j];
}
}
dp[i][j] = min;
}
}
cout << "Chain " << Case++ << endl;
cout << "Total distance sum = " << dp[k][n] << endl << endl;
}
return 0;
}