Post Office POJ - 1160(DP)

China☆狼群 提交于 2020-02-07 17:34:40

There is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each village is identified with a single integer coordinate. There are no two villages in the same position. The distance between two positions is the absolute value of the difference of their integer coordinates.

Post offices will be built in some, but not necessarily all of the villages. A village and the post office in it have the same position. For building the post offices, their positions should be chosen so that the total sum of all distances between each village and its nearest post office is minimum.

You are to write a program which, given the positions of the villages and the number of post offices, computes the least possible sum of all distances between each village and its nearest post office.
Input
Your program is to read from standard input. The first line contains two integers: the first is the number of villages V, 1 <= V <= 300, and the second is the number of post offices P, 1 <= P <= 30, P <= V. The second line contains V integers in increasing order. These V integers are the positions of the villages. For each position X it holds that 1 <= X <= 10000.
Output
The first line contains one integer S, which is the sum of all distances between each village and its nearest post office.
Sample Input
10 5
1 2 3 6 7 9 11 22 44 50
Sample Output
9

题意:
n个村庄,p个村庄放邮局。求每个村庄到离自己最近的邮局距离和

思路:
首先一个结论:假设n个村庄放一个邮局,那么放在中间最好。

且假设是n个村庄,中间为(1 + n) / 2。那么对于n+1个村庄的最优点:
假设n为奇数,那么(1 + n) / 2 = (1 + 1 + n) / 2
假设n为偶数,那么(1 + n) / 2 + 1=(1 + 1 + n) / 2
且此时(1 + n) / 2与(1 + n) / 2 + 1均可看作n个村庄的中点。
结论是n个村庄和n+1个村庄的最优点可以相同。

定义dis[i][j]为i到j内放一个邮局的最小距离和
f[i][j]为前i个村庄放j个邮局的最小距离和。
f[i][j] = min{ f[k][j - 1] = dis[k + 1][i] }

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int f[305][305];
int dis[305][305];
int a[305];
int n,p;

void init()
{
    for(int i = 1;i <= n;i++)
    {
        for(int j = i + 1;j <= n;j++)
        {
            dis[i][j] = dis[i][j - 1] + a[j] - a[(i + j) >> 1];
        }
    }
}

void DP()
{
    memset(f,0x3f,sizeof(f));
    for(int i = 1;i <= p;i++)f[i][i] = 0;
    for(int i = 1;i <= n;i++)f[i][1] = dis[1][i];
    for(int j = 2;j <= p;j++)
    {
        for(int i = j + 1;i <= n;i++)
        {
            for(int k = j - 1;k < i;k++)
            {
                f[i][j] = min(f[i][j],f[k][j - 1] + dis[k + 1][i]);
            }
        }
    }
}

int main()
{
    scanf("%d%d",&n,&p);
    for(int i = 1;i <= n;i++)scanf("%d",&a[i]);
    init();
    DP();
    printf("%d\n",f[n][p]);
    return 0;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!