ZOJ1196

来源:互联网 发布:unity3d游戏开发书籍 编辑:程序博客网 时间:2024/06/05 16:02

题目链接: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;

}