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;
}

浙公网安备 33010602011771号