题目链接:
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; }