虽然dp方程很好写,就是这个期望不知道怎么求,昨晚的BC也是
题目问题抽象之后为:在一个x坐标轴上有N个点,每个点上有一个概率值,可以修M个工作站,
求怎样安排这M个工作站的位置,使得这N个点都走到工作站的距离期望值最小?
解题报告人:SpringWater(GHQ)
解题思路:状态方程:dp[i][j] = min{ dp[i - 1][k - 1] + cost[k][j] }dp[i][j]表示在1到j修i个站,的最小期望值,
cost【k】【j】是我预处理的k到j这段区间修一个工作站的期望值 ,因为在求cost【k】【j】具
有单调性,所以可以在O(n^2)复杂度算出
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<map> 5 #define INF ((1<<23)-1) 6 using namespace std; 7 map<int ,double> mp; 8 double f[1010][60]; 9 typedef struct 10 { 11 int x; double p; 12 }Point; 13 Point pt[1010]; 14 int kk,m; 15 16 void initial() 17 { 18 for(int i=0;i<=1000;i++) 19 for(int j=0;j<=50;j++) 20 f[i][j]=INF; 21 for(int i=0;i<=m;i++) 22 for(int j=i;j<=m;j++) 23 f[i][j]=0.0; 24 } 25 26 int main() 27 { 28 int k,i,j,l,x; double p; 29 while( scanf("%d%d",&kk,&m),kk+m ) 30 { 31 mp.clear(); 32 initial(); 33 for(i=1;i<=kk;i++) 34 { 35 scanf("%d",&l); 36 for(j=1;j<=l;j++) 37 { 38 scanf("%d%lf",&x,&p); 39 mp[x]+=p; 40 } 41 } 42 map<int,double>::iterator it; 43 j=1; 44 for( it=mp.begin(); it!=mp.end();it++,j++) 45 { 46 pt[j].x=(it->first); 47 pt[j].p=(it->second); 48 } 49 int n=j-1; 50 for( i=1;i<=n;i++ ) 51 { 52 for(j=1;j<=m && j<=i; j++ ) 53 { 54 f[i][j]=INF; 55 double pre=0.000,suf=0.000; 56 int cur=i; double add=0.000; 57 for(k=i-1;k>=j-1;k--) 58 { 59 if( k+1 != i ) 60 { 61 pre+=pt[k+1].p; 62 add+=pt[k+1].p*(pt[cur].x-pt[k+1].x); 63 } 64 while( pt[cur].p+suf < pre ) 65 { 66 suf+=pt[cur].p; 67 cur--; 68 pre-=pt[cur].p; 69 add-=pt[cur].p*(pt[cur+1].x-pt[cur].x); 70 add+=pt[cur+1].p*(pt[cur+1].x-pt[cur].x); 71 add-=pre*(pt[cur+1].x-pt[cur].x); 72 add+=(suf-pt[cur+1].p)*(pt[cur+1].x-pt[cur].x); 73 } 74 f[i][j]=min(f[i][j],f[k][j-1]+add); 75 } 76 } 77 } 78 printf("%.2lf\n",f[n][m]); 79 } 80 return 0; 81 }