题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=196
题目大意:一条公路上,总共有n个快餐厅,总公司在坐标0上,快餐店离总公司有di的距离,在0~n个快餐店之间建造k个仓库,仓库的位置都处在快餐店的位置,试设计程序使快餐店到仓库的距离和最小。
思路:设dp[i][j]为前i个快餐店间建造j个仓库,
dp[i][j] = min{ dp[i][j], dp[k][j -1] +mindis[k+1][i] }, i > 0, j > 0, j-1 <= k <= i-1;
mindis[x+1][i],是从第x+1,……,i个快餐店到仓库的距离最小和。
我的AC Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int dp[201][31];
int dis[201][201];
int d[201];
int n, m;
int min(int a, int b)
{
return a < b ? a : b;
}
void mindis (int n)
{
int i, j, k, mid;
for (i = 1; i < n; i++)
{
for (j = i; j <= n; j++)
{
mid = (j + i) / 2;
for (k = i; k < mid; k++)
dis[i][j] += d[mid] - d[k];
for (k = mid + 1; k <= j; k++)
dis[i][j] += d[k] - d[mid];
}
}
}
int main()
{
int i, j, k, t=1;
while (scanf ("%d%d", &n, &m) != EOF)
{
if (!n && !m) break;
for (i = 1; i <= n; i++)
scanf ("%d", &d[i]);
memset (dp, 1000000, sizeof (dp));
memset (dis, 0, sizeof (dis));
mindis(n);
for (i = 1; i <= n; i++)
dp[i][1] = dis[1][i];
for (i = 1; i <= n; i++)
{
for (j = 2; j <= m; j++)
{
for (k = j - 1; k <= i - 1; k++)
dp[i][j] = min ( dp[i][j], dp[k][j-1] + dis[k+1][i]);
}
}
printf ("Chain %d/nTotal distance sum = %d/n/n", t++, dp[n][m]);
}
return 0;
}