题目大意:
一条街上有很多个餐厅,现在要在n个餐厅中选取m个作为仓库。
使得其他的餐厅到这些仓库的距离的和最小。
思路分析:
状态方程: dp [i] [j] 表示 前 j 个餐厅已经建了 i 个仓库。
转移方程: dp[i] [j] = min ( dp[i-1] [k] + cost[k+1][j] ) ...cost[ p ][ q ] 表示在p q 之间建立一个仓库的最小花费。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[40][300];
int cost[300][300];
int pos[300];
int Abs(int x)
{
return x>0?x:-x;
}
int main()
{
int n,m,cas=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0 && m==0)break;
for(int i=1;i<=n;i++)
scanf("%d",&pos[i]);
memset(cost,0,sizeof cost);
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
for(int k=i;k<=j;k++)
{
cost[i][j]+=Abs(pos[k]-pos[(i+j)>>1]);
}
}
}
memset(dp,0x3f,sizeof dp);
for(int i=1;i<=m;i++)dp[i][i]=0;
for(int i=1;i<=n;i++)dp[1][i]=cost[1][i];//初始化
for(int i=2;i<=m;i++)//已经初始化了 i == 1 的情况
{
for(int j=1;j<=n;j++)
{
for(int k=i-1;k<=j;k++)//从 i-1 开始
{
dp[i][j]=min(dp[i][j],dp[i-1][k]+cost[k+1][j]);
}
}
}
printf("Chain %d\nTotal distance sum = %d\n\n",cas++,dp[m][n]);
}
return 0;
}