简单dp-poj-2231-Moo Volume

来源:互联网 发布:东莞菲凡网络 编辑:程序博客网 时间:2024/05/18 01:42

题目链接:

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 11000ll 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;}