有一点要注意 数组最好开大一点。。。。300会WA
dp【i】【j】表示从0到i的村庄设置j个邮局的最优解,那么转移方程就是:
dp【i】【j】 = min( dp【k】【j-1】 +cost【k】【i】 ) j - 1《k《=i
cost【k】【i】表示从k到i的村庄只设置一个邮局的最优解(邮局设在中位数的位置)
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
int dp[3000][30];
int cost[3000][3000];
int V, P;
int pos[3000];
void init(){
for( int i = 0; i < V; i++ ){
for( int j = i; j < V; j++ ){
int mid = ( i + j ) / 2;
cost[i][j] = 0;
for( int k = i; k < mid; k++ ){
cost[i][j] += pos[mid] - pos[k];
}
for( int k = mid + 1; k <= j; k++ ){
cost[i][j] += pos[k] - pos[mid];
}
}
}
}
int DFS( int numv, int nump ){
if( numv + 1 < nump ){
return MAX;
}
if( nump == 1 ){
return cost[0][numv];
}
if( dp[numv][nump] != -1 ){
return dp[numv][nump];
}
int ans = MAX;
for( int i = nump - 1; i <= numv; i++ ){
ans = min( ans, cost[i][numv] + DFS( i - 1, nump - 1 ) );
}
return dp[numv][nump] = ans;
}
int main(){
while( scanf( "%d%d", &V, &P ) != EOF ){
for( int i = 0; i < V; i++ ){
scanf( "%d", &pos[i] );
}
init();
memset( dp, -1, sizeof( dp ) );
cout << DFS( V - 1, P ) << endl;
}
return 0;
}