题意 : 有n个饭店,要求建k个供应点,要求每个供应点一定要建造在某个饭店的位置上,然后饭店都到最近的供应点拿货,求出所有饭店到最近的供应点的最短距离。
思路 : 一开始没看出来是DP,后来想想就想通了。预处理,如果要在下标为 i 到 j 的饭店建一个供应点,那一定是在下标为(i+j)/2的位置建造的,状态转移方程:dp[i][j] = dp[i-1][k-1]+dis[k][j](i <= k <= j) ,dp[i][j]代表的是在前 j 个饭店中建了 i 个供应点的最小距离。方程代表的是在前k-1个饭店中已经建了i-1个供应点的最小距离再加上从第k个饭店到第j个饭店建一个供应点增加的距离。如果不明白可以看这里,链接
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 6 using namespace std; 7 const int maxn = 0x7fffffff ; 8 9 int a[210] ,dis[210][210],dp[210][210]; 10 11 int main() 12 { 13 int n,k ,cas = 1; 14 while(~scanf("%d %d",&n,&k)) 15 { 16 if(n == 0 && k == 0 ) break ; 17 for(int i = 1 ; i <= n ; i++) 18 scanf("%d",&a[i]) ; 19 for(int i = 1 ; i <= n ; i++) 20 { 21 for(int j = i ; j <= n ; j++) 22 { 23 dis[i][j] = 0 ; 24 for(int k = i ; k <= j ; k++) 25 dis[i][j] += fabs(a[k]-a[(i+j)/2] ); 26 } 27 } 28 memset(dp,0,sizeof(dp)) ; 29 for(int i = 1 ; i <= n ; i++) 30 dp[1][i] = dis[1][i] ; 31 for(int i = 2 ; i <= k; i++) 32 { 33 for(int j = 2 ; j <= n ; j++) 34 { 35 int minn = maxn ; 36 for(int k = i ; k <= j ; k++) 37 { 38 if(dp[i-1][k-1]+dis[k][j] < minn) 39 minn = dp[i-1][k-1]+dis[k][j] ; 40 } 41 dp[i][j] = minn ; 42 } 43 } 44 printf("Chain %d\nTotal distance sum = %d\n\n",cas++,dp[k][n]); 45 } 46 return 0; 47 }