简单dp-poj-2231-Moo Volume

2014-11-23 23:40:08 · 作者: · 浏览: 3
题目大意:
给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  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#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; }