简单dp-poj-2231-Moo Volume

题目链接:

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

题目大意:

给n个位置,求所有位置到其他n-1个位置的距离总和。

解题思路:

简单dp.

o(n^2)的时间复杂度会超。先对这n个位置排序。然后从前置后,和从后到前各扫一遍,分别求出当前位置到前面所有位置的距离总和,以及当前位置到后面所有位置的总和。

从前置后扫一遍,dp[i]表示位置i到前面所有位置的总和。dp[i]=(sa[i]-sa[i-1])*(i-1)+dp[i-1]. 对于i到前面的每一位置k,都可以表示dis[i-1][k]+dis[i-1][i]这样就可以利用dp[i-1],加上dis[i-1][i]的个数就行了。

类似的从后往前扫一遍,求出当前位置到后面位置的所有的和。

代码:

 

#include<iostream>

#include<cmath>

#include<cstdio>

#include<sstream>

#include<cstdlib>

#include<string>

#include<cstring>

#include<algorithm>

#include<vector>

#include<map>

#include<set>

#include<stack>

#include<list>

#include<queue>

#include<ctime>

#include<bitset>

#define eps 1e-6

#define INF 0x3f3f3f3f

#define PI acos(-1.0)

#define ll __int64

#define LL long long

#define lson l,m,(rt<<1)

#define rson m+1,r,(rt<<1)|1

#define M 1000000007

#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;



#define Maxn 11000



ll dp[Maxn],sa[Maxn];



int main()

{

    int n;



    while(~scanf("%d",&n))

    {

        ll ans=0;



        for(int i=1;i<=n;i++)

            scanf("%I64d",&sa[i]);



        sort(sa+1,sa+n+1);

        dp[1]=0;

        for(int i=2;i<=n;i++)

        {  //到前面任何位置k,都可以先到i-1,然后从i-1到k利用dp[i-1]

            dp[i]=(sa[i]-sa[i-1])*(i-1)+dp[i-1];

            ans+=dp[i];

        }

        dp[n]=0;

        for(int i=n-1;i>=1;i--)

        {

            dp[i]=(sa[i+1]-sa[i])*(n-i)+dp[i+1];

            ans+=dp[i];

        }

        printf("%I64d\n",ans);

    }

   return 0;

}








 

 

你可能感兴趣的:(poj)