话说这题第一眼看去 像以前的POJ上一道四边形优化的题目 不过没有权重 所以一个区间最优点不是在中位数上
但是可以确定的是 他的答案是有单调性的 V型 然后肯定可以在点上 。
那么处理出一段区间 就是简单的dp了。
(~~~~~~不知道为什么从前往后推 cost 一直都错,结果参考了别人的代码才过的 = = !! 写法的问题 果然还是太菜了)
cost 是可以一位一位移动的 所以才是O(n^2)解决的
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;
#define maxn 1010
map<int,double>mp;
map<int,double>::iterator it;
struct node
{
double x;
double p;
};
node r[maxn];
double cost[maxn][maxn];
double dp[55][maxn];
double sum[maxn];
int main()
{
int n,m,c,x,cnt;
double p;
while(scanf("%d%d",&n,&m)&&n+m)
{
cnt=1;
mp.clear();
for(int i=0;i<n;i++)
{
scanf("%d",&c);
for(int j=0;j<c;j++)
{
scanf("%d%lf",&x,&p);
mp[x]+=p;
}
}
for(it=mp.begin();it!=mp.end();it++,cnt++)
{
r[cnt].x=it->first;
r[cnt].p=it->second;
}
sum[0]=0;
for(int i=1;i<cnt;i++)
{
cost[i][i]=0;
sum[i]=sum[i-1]+r[i].p;
}
for(int i=cnt-1;i>=1;i--)
{
double suml=0;
double sumr=0;
int cur=i;
double sum=0;
double lp=0;
double rp=r[i].p;
double temp=0;
for(int j=i-1;j>=1;j--)
{
suml+=r[j].p*(r[cur].x-r[j].x);
lp+=r[j].p;
temp=suml+sumr;
while(cur>1&&temp>suml+sumr+(rp-lp)*(r[cur].x-r[cur-1].x))
{
suml-=(lp)*(r[cur].x-r[cur-1].x);
sumr+=(rp)*(r[cur].x-r[cur-1].x);
cur--;
lp-=r[cur].p;
rp+=r[cur].p;
temp=suml+sumr;
}
cost[j][i]=temp;
}
}
for(int i=0;i<=m;i++)
{
for(int j=0;j<cnt;j++)
{
dp[i][j]=0x3f3f3f3f;
}
dp[i][i]=0;
}
for(int i=1;i<=m;i++)
{
for(int j=0;j<cnt;j++)
{
for(int k=j+1;k<cnt;k++)
{
dp[i][k]=min(dp[i][k],dp[i-1][j]+cost[j+1][k]);
}
}
}
printf("%.2lf\n",dp[m][cnt-1]);
}
return 0;
}