P2466 [SDOI2008] Sue 的小球题解

P2466 [SDOI2008] Sue 的小球题解

P2466 [SDOI2008] Sue 的小球题解

题目描述

Sue 和 Sandy 最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue 有一支轻便小巧的小船。然而,Sue 的目标并不是当一个海盗,而是要收集空中漂浮的彩蛋,Sue 有一个秘密武器,只要她将小船划到一个彩蛋的正下方,然后使用秘密武器便可以在瞬间收集到这个彩蛋。然而,彩蛋有一个魅力值,这个魅力值会随着彩蛋在空中降落的时间而降低,Sue 要想得到更多的分数,必须尽量在魅力值高的时候收集这个彩蛋,而如果一个彩蛋掉入海中,它的魅力值将会变成一个负数,但这并不影响 Sue 的兴趣,因为每一个彩蛋都是不同的,Sue 希望收集到所有的彩蛋。

然而 Sandy 就没有 Sue 那么浪漫了,Sandy 希望得到尽可能多的分数,为了解决这个问题,他先将这个游戏抽象成了如下模型:

将大海近似的看做 x 轴建立一个竖直的平面直角坐标系,Sue 所在的初始位置在 x 轴上。

一开始空中有 N 个彩蛋,对于第 i 个彩蛋,他的初始位置用整数坐标 (xi​,yi​) 表示,游戏开始后,它匀速沿 y 轴负方向下落,速度为 vi​ 单位距离/单位时间。Sue 的初始位置为 (x0​,0),Sue 可以沿 x 轴的正方向或负方向移动,Sue 的移动速度是 1 单位距离/单位时间,使用秘密武器得到一个彩蛋是瞬间的,得分为当前彩蛋的 y 坐标的千分之一。

现在,Sue 和 Sandy 请你来帮忙,为了满足 Sue 和 Sandy 各自的目标,你决定在收集到所有彩蛋的基础上,得到的分数最高。

输入格式

第一行为两个整数 N, x0​ 用一个空格分隔,表示彩蛋个数与 Sue 的初始位置。

第二行为 N 个整数 xi​,每两个数用一个空格分隔,第 i 个数表示第 i 个彩蛋的初始横坐标。

第三行为 N 个整数 yi​,每两个数用一个空格分隔,第 i 个数表示第 i 个彩蛋的初始纵坐标。

第四行为 N 个整数 vi​,每两个数用一个空格分隔,第 i 个数表示第 i 个彩蛋匀速沿 y 轴负方向下落的的速度。

输出格式

一个实数,保留三位小数,为收集所有彩蛋的基础上,可以得到最高的分数。

输入输出样例

输入 #1复制

3 0
-4 -2 2
22 30 26
1 9 8

输出 #1复制

0.000

说明/提示

对于 30% 的数据, N≤20。

对于 60% 的数据, N≤100。

对于 100% 的数据,−104≤xi​,yi​≤104,0≤vi​≤104,N≤1000

思路

DP题,区间DP即可。

代码见下

#include<bits/stdc++.h>
using namespace std;
struct one{
	long long x,y,v;
}aa[1005];
long long n,x,ss,f[1005][1005][2],b[1005],c[1005];
double cw;
bool cmp(one a1,one b1){
	return a1.x<b1.x;
}
int main(){
	cin>>n>>x;
	for(int i=1;i<=n;i++){
		cin>>aa[i].x;		
	}
	for(int i=1;i<=n;i++){
		cin>>aa[i].y;	
		ss+=aa[i].y;	
	}
	for(int i=1;i<=n;i++){
		cin>>aa[i].v;	
		b[i]=b[i-1]+aa[i].v;		
	}
	for(int i=n;i>=1;i--){
		c[i]=c[i+1]+aa[i].v;		
	}
	sort(aa+1,aa+n+1,cmp);
	for(int i=1;i<=n;i++){
		b[i]=b[i-1]+aa[i].v;		
	}
	for(int i=n;i>=1;i--){
		c[i]=c[i+1]+aa[i].v;		
	}	
	//memset(f,0x3f3f3f3f,sizeof(f));
	for(int i=1;i<=n;i++){
		f[i][i][0]=f[i][i][1]=abs(x-aa[i].x)*b[n];
	}
	for(int i=2;i<=n;i++){
		for(int l=1;l+i-1<=n;l++){
			long long r=l+i-1;
			f[l][r][1]=min(f[l][r-1][1]+abs(aa[r].x-aa[r-1].x)*(b[l-1]+c[r]),f[l][r-1][0]+abs(aa[r].x-aa[l].x)*(b[l-1]+c[r]));
			f[l][r][0]=min(f[l+1][r][0]+abs(aa[l+1].x-aa[l].x)*(b[l]+c[r+1]),f[l+1][r][1]+abs(aa[r].x-aa[l].x)*(b[l]+c[r+1]));
		}		
	}
	cw=(long double)ss-(long double)min((long double)f[1][n][0],(long double)f[1][n][1]);
	cw/=1000.000;
	//cout<<cw<<endl;
	printf("%.3lf\n",cw);
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct one{
	long long x,y,v;
}aa[1005];
long long n,x,ss,f[1005][1005][2],b[1005],c[1005];
double cw;
bool cmp(one a1,one b1){
	return a1.x<b1.x;
}
int main(){
	cin>>n>>x;
	for(int i=1;i<=n;i++){
		cin>>aa[i].x;		
	}
	for(int i=1;i<=n;i++){
		cin>>aa[i].y;	
		ss+=aa[i].y;	
	}
	for(int i=1;i<=n;i++){
		cin>>aa[i].v;	
		b[i]=b[i-1]+aa[i].v;		
	}
	for(int i=n;i>=1;i--){
		c[i]=c[i+1]+aa[i].v;		
	}
	sort(aa+1,aa+n+1,cmp);
	for(int i=1;i<=n;i++){
		b[i]=b[i-1]+aa[i].v;		
	}
	for(int i=n;i>=1;i--){
		c[i]=c[i+1]+aa[i].v;		
	}	
	//memset(f,0x3f3f3f3f,sizeof(f));
	for(int i=1;i<=n;i++){
		f[i][i][0]=f[i][i][1]=abs(x-aa[i].x)*b[n];
	}
	for(int i=2;i<=n;i++){
		for(int l=1;l+i-1<=n;l++){
			long long r=l+i-1;
			f[l][r][1]=min(f[l][r-1][1]+abs(aa[r].x-aa[r-1].x)*(b[l-1]+c[r]),f[l][r-1][0]+abs(aa[r].x-aa[l].x)*(b[l-1]+c[r]));
			f[l][r][0]=min(f[l+1][r][0]+abs(aa[l+1].x-aa[l].x)*(b[l]+c[r+1]),f[l+1][r][1]+abs(aa[r].x-aa[l].x)*(b[l]+c[r+1]));
		}		
	}
	cw=(long double)ss-(long double)min((long double)f[1][n][0],(long double)f[1][n][1]);
	cw/=1000.000;
	//cout<<cw<<endl;
	printf("%.3lf\n",cw);
	return 0;
}

posted @ 2025-10-24 20:37  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源