动态规划,主要是用单调性求区间的最小期望。
代码如下:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 #include<map> 9 #define MAX 1004 10 #define inf 1<<22 11 using namespace std; 12 double dp[MAX][MAX],b,add,l,r; 13 map<int,double>q; 14 struct node 15 { 16 int x; 17 double p; 18 }an[MAX]; 19 void init(int m) 20 { 21 int i,j; 22 for(i=0;i<=1000;i++) 23 for(j=0;j<=50;j++) 24 dp[i][j]=inf; 25 for(i=0;i<=m;i++) 26 for(j=i;j<=m;j++) 27 dp[i][j]=0.0; 28 } 29 int main(){ 30 int n,m,k,i,j,a; 31 while(scanf("%d%d",&n,&m)&&(n+m)){ 32 q.clear(); 33 for(i=0;i<n;i++){ 34 scanf("%d",&k); 35 for(j=0;j<k;j++){ 36 scanf("%d%lf",&a,&b); 37 q[a]+=b; 38 } 39 } 40 n=0; 41 for(map<int,double>::iterator it=q.begin();it!=q.end();it++){ 42 an[++n].x=it->first; 43 an[n].p=it->second; 44 } 45 init(m); 46 for(i=1;i<=n;i++){ 47 for(j=1;j<=m&&j<=i;j++){ 48 dp[i][j]=inf; 49 double pre=0.0,suf=0.0; 50 int cur=i;add=0.0; 51 for(k=i-1;k>=j-1;k--){ 52 if(k+1!=i){ 53 pre+=an[k+1].p; 54 add+=an[k+1].p*(an[cur].x-an[k+1].x); 55 } 56 while(an[cur].p+suf<pre){ 57 suf+=an[cur].p; 58 cur--; 59 pre-=an[cur].p; 60 int t=an[cur+1].x-an[cur].x; 61 add-=an[cur].p*t; 62 add+=an[cur+1].p*t; 63 add-=pre*t; 64 add+=(suf-an[cur+1].p)*t; 65 } 66 dp[i][j]=min(dp[i][j],dp[k][j-1]+add); 67 } 68 } 69 } 70 printf("%.2lf ",dp[n][m]); 71 } 72 return 0; 73 }