嗯,题意比较容易理解,在高速公路旁有一些快餐店,然后每一个快餐店距高速出口的距离给出,在这几个快餐店中的K个建仓库,使每个快餐店到其最近的仓库距离和最短。
并输出方案(可能有多个,求解任意一个)
典型的DP 前i个神马东西里面选几个东西的问题吧属于,但是路径不会!参考别人代码,不要喷我!
/*
转移方程:dp[i][j] = min(dp[k][j-1] + cost[k+1][i]);
表示前i个餐馆建设j个仓库 = 前k个餐馆建设j-1个仓库 + k+1个参观到第i个餐馆建设一个仓库的最小值
cost[i][j] 表示从i到j建设仓库路程最小值 ,显而易见 在(i+j)/2处建设可得距离差最短(不明白可以简单模拟下)
路径存储:没有想出来好的办法,借鉴别人思路,递归求解。
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define INF 0x6ffffff
#define NN 210
int d[NN],dp[NN][NN/6],cost[NN][NN];
int from[NN][NN/6],to[NN][NN/6],at[NN][NN/6];
int n,K;
int PrintPath(int i,int j)
{
int num;
if(j<=0 ||i<=0)return 1;
num = PrintPath(from[i][j]-1,j-1);
printf("Depot %d at restaurant %d serves ",num,at[i][j]);
if(from[i][j] == to[i][j])printf("restaurant %d\n",from[i][j]);
else printf("restaurants %d to %d\n",from[i][j],to[i][j]);
return num +1;
}
void DP()
{
int i,j,mid,k,sum,min;
for(i=1;i<=n;i++){
for(j=i;j<=n;j++){
mid = (i+j)/2;
for(k=i;k<mid;k++)
cost[i][j]+=d[mid]-d[k];
for(k=mid+1;k<=j;k++)
cost[i][j]+=d[k]-d[mid];
}
}//计算cost[i][j]
//DP前初始化
for(i=1;i<=n;i++)dp[i][0]=INF;
for(i=1;i<=n;i++){
for(j=1;j<=K && j<=i;j++){
min = INF;
for(k=j-1;k<i;k++){
sum = dp[k][j-1] + cost [k+1][i];
if(sum < min){
min = sum;
from[i][j] = k+1;
to[i][j] = i;
at[i][j] = (k+i+1)/2;
}
}
dp[i][j]=min;
}
}
}
int main()
{
int i,c=1;
while(~scanf("%d%d",&n,&K),n||K){
for(i=1;i<=n;i++)scanf("%d",&d[i]);
printf("Chain %d\n",c++);
DP();
PrintPath(n,K);
printf("Total distance sum = %d\n\n",dp[n][K]);
memset(dp,0,sizeof(dp));
memset(cost,0,sizeof(cost));
}
return 0;
}