思路:
这题和1227的求法一样,只不过1227是小数据,暴力下,就能进行预处理。
这题的预处理区间期望cost[i][j]需要利用单调性。
即假使以pos位置为安排的点,那么这个区间在其左边的概率为l,右边的概率为r,总期望为sum。如果将安排点从pos放到pos-1
该区间增加的期望为r*(p[pos].x-p[pos-1].x)
减少的期望为l*(p[pos].x-p[pos-1].x)
如果减少的超过增加的,那么pos-1就比pos好。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #define Maxn 1010 using namespace std; double dp[Maxn][60],cost[Maxn][Maxn]; struct Point{ int x; double p; }p[Maxn]; map<int ,double> vi; int main() { int n,m,i,j,l,x,k; double cc; while(scanf("%d%d",&n,&m)!=EOF,n||m) { memset(dp,0,sizeof(dp)); memset(p,0,sizeof(p)); memset(cost,0,sizeof(cost)); vi.clear(); int mx=0; for(i=1;i<=n;i++) { scanf("%d",&l); while(l--) { scanf("%d%lf",&x,&cc); vi[x]+=cc; } } int cnt=0; map<int ,double> ::iterator it; for(it=vi.begin();it!=vi.end();it++) p[++cnt].x=it->first,p[cnt].p=it->second; double l,r,sum; int pos; double t; for(i=cnt;i>1;i--) { l=r=sum=0; r=p[i].p; pos=i; for(j=i-1;j>=1;j--) { l+=p[j].p; sum+=p[j].p*(p[pos].x-p[j].x); while(pos>1&&(t=(r-l)*(p[pos].x-p[pos-1].x))<0) { sum+=t; pos--; l-=p[pos].p; r+=p[pos].p; } cost[j][i]=sum; } } for(i=1;i<=cnt;i++) dp[i][1]=cost[1][i]; for(i=1;i<=m;i++) dp[1][i]=0; for(k=2;k<=m;k++) { for(i=1;i<=cnt;i++) { if(i<=k) {dp[i][k]=0;continue;} dp[i][k]=1e20; for(j=i-1;j>=1;j--) dp[i][k]=min(dp[i][k],dp[j][k-1]+cost[j+1][i]); } } printf("%.2lf ",dp[cnt][m]); } return 0; }