简单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
",ans);
    }
   return 0;
}




原文地址:https://www.cnblogs.com/keanuyaoo/p/3366058.html