POJ 1160 Post Office

http://poj.org/problem?id=1160

 

  这是一道DP的题,用w[i][j]代表用一个邮局覆盖第i个到第j个点所得到的最小距离和。

f[i][j]代表用前i个邮局覆盖前j个点所得到的最小距离和。然后根据这里我们可以推

出状态转移方程为:f[i][j] = min( f[i][j ] , f[i - 1][k] + w[k + 1][j] )  ( k < j).

/*Accepted    528K    79MS    C++    1195B    2012-08-07 14:23:15*/

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<algorithm>

using namespace std;



const int MAXP = 35, MAXV = 305, INF = 0x3f3f3f3f;

int a[MAXV], f[MAXP][MAXV], w[MAXV][MAXV];

int p, v;



void init()

{

    int i, j, k, m;

    for(i = 1; i <= v; i ++)

        scanf("%d", &a[i]);

    for(i = 1; i <= v; i ++)

    {

        for(j = i; j <= v; j ++)

        {

            w[i][j] = 0;

            m = i + j >> 1;

            for(k = i; k <= j; k ++)

            {

                if(k <= m)

                    w[i][j] += (a[m] - a[k]);

                if(k > m)

                    w[i][j] += (a[k] - a[m]);

            }

        }

    }

    for(i = 1; i <= p; i ++)

        for(j = 1; j <= v; j ++)

            f[i][j] = INF;

    for(j = 1; j <= v; j ++)

        f[1][j] = w[1][j];

}



void dp()

{

    int i, j, k;

    for(i = 2; i <= p; i ++)

        for(j = 2; j <= v; j ++)

            for(k = i; k <= j; k ++)

                f[i][j] = min(f[i][j], f[i - 1][k] + w[k + 1][j]);

}



int main()

{

    while(scanf("%d%d", &v, &p) == 2)

    {

        init();

        dp();

        printf("%d\n", f[p][v]);

    }

    return 0;

}

你可能感兴趣的:(Office)