记录编号 87155 评测结果 AAAAAAAAAA
题目名称 [SDOI 2008]Sue的小球 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.069 s
提交时间 2014-02-01 19:20:02 内存使用 10.06 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
using namespace std;
const int SIZEN=1010,INF=0x7fffffff/2;
int N,X0;
int startpos;
int totY=0;
pair<int,int> balls[SIZEN];//x坐标和速度
int preV[SIZEN]={0};
int f1[SIZEN][SIZEN]={0},f2[SIZEN][SIZEN]={0};
//f1是在左端,f2是在右端
bool vis1[SIZEN][SIZEN]={0},vis2[SIZEN][SIZEN]={0};
inline int W(int x,int y){//除了区间[x,y]的所有速度和
	return preV[N]-(preV[y]-preV[x-1]);
}
int DP1(int,int);
int DP2(int,int);
int DP1(int x,int y){//计算f1
	if(balls[x].first>X0||balls[y].first<X0) return INF;//这样的情况在最优移动中是不可能出现的
	if(vis1[x][y]) return f1[x][y];
	vis1[x][y]=true;
	if(x==y) return f1[x][y]=0;
	f1[x][y]=INF;
	f1[x][y]=min(f1[x][y],DP2(x+1,y)+(balls[y].first-balls[x].first)*W(x+1,y));
	f1[x][y]=min(f1[x][y],DP1(x+1,y)+(balls[x+1].first-balls[x].first)*W(x+1,y));
	return f1[x][y];
}
int DP2(int x,int y){//计算f2
	if(balls[x].first>X0||balls[y].first<X0) return INF;//这样的情况在最优移动中是不可能出现的
	if(vis2[x][y]) return f2[x][y];
	vis2[x][y]=true;
	if(x==y) return f2[x][y]=0;//一定收敛到初始位置
	f2[x][y]=INF;
	f2[x][y]=min(f2[x][y],DP2(x,y-1)+(balls[y].first-balls[y-1].first)*W(x,y-1));
	f2[x][y]=min(f2[x][y],DP1(x,y-1)+(balls[y].first-balls[x].first)*W(x,y-1));
	return f2[x][y];
}
void read(void){
	scanf("%d%d",&N,&X0);
	for(int i=1;i<=N;i++) scanf("%d",&balls[i].first);
	int y;
	for(int i=1;i<=N;i++) scanf("%d",&y),totY+=y;
	for(int i=1;i<=N;i++) scanf("%d",&balls[i].second);
	N++;
	balls[N]=make_pair(X0,0);//为了简化问题,设一个起点立刻能接到的小球,其得分为0(totY不改变),速度为0
}
int main(){
	freopen("sueball.in","r",stdin);
	freopen("sueball.out","w",stdout);
	read();
	sort(balls+1,balls+1+N);
	for(int i=1;i<=N;i++) preV[i]=preV[i-1]+balls[i].second;
	int numdec=min(DP1(1,N),DP2(1,N));
	double ans=(totY-numdec+0.0)/1000.0;
	printf("%.3lf\n",ans);
	return 0;
}