P2466 [SDOI2008] Sue 的小球
P2466 [SDOI2008] Sue 的小球
题目描述
Sue 和 Sandy 最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue 有一支轻便小巧的小船。然而,Sue 的目标并不是当一个海盗,而是要收集空中漂浮的彩蛋,Sue 有一个秘密武器,只要她将小船划到一个彩蛋的正下方,然后使用秘密武器便可以在瞬间收集到这个彩蛋。然而,彩蛋有一个魅力值,这个魅力值会随着彩蛋在空中降落的时间而降低,Sue 要想得到更多的分数,必须尽量在魅力值高的时候收集这个彩蛋,而如果一个彩蛋掉入海中,它的魅力值将会变成一个负数,但这并不影响 Sue 的兴趣,因为每一个彩蛋都是不同的,Sue 希望收集到所有的彩蛋。
然而 Sandy 就没有 Sue 那么浪漫了,Sandy 希望得到尽可能多的分数,为了解决这个问题,他先将这个游戏抽象成了如下模型:
将大海近似的看做
一开始空中有
现在,Sue 和 Sandy 请你来帮忙,为了满足 Sue 和 Sandy 各自的目标,你决定在收集到所有彩蛋的基础上,得到的分数最高。
输入格式
第一行为两个整数
第二行为
第三行为
第四行为
输出格式
一个实数,保留三位小数,为收集所有彩蛋的基础上,可以得到最高的分数。
样例 #1
样例输入 #1
3 0
-4 -2 2
22 30 26
1 9 8
样例输出 #1
0.000
提示
对于
对于
对于
Solution
首先需要知道的是,当经过一个彩蛋时肯定是会将彩蛋捡起来的,因为如果不捡,如果等之后再来捡的话这个彩蛋带来的贡献会减少,反而不如经过就直接捡起(这道题
因为每个彩蛋在输入时是无序的,所以在处理前应该先把彩蛋按照
考虑动态规划,设
换一个方向,将
因为收集完
设
类似地,也可以推出
根据这些信息,代码就很好写出来了。
需要注意的是,因为数据范围的原因,
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<limits.h>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
template<typename T> void read(T &k)
{
k=0;
T flag=1;char b=getchar();
while (b<'0' || b>'9') {flag=(b=='-')?-1:1;b=getchar();}
while (b>='0' && b<='9') {k=(k<<3)+(k<<1)+(b^48);b=getchar();}
k*=flag;
}
const long long _SIZE=1e3;
struct BALL{
long long x,y,v;
}ball[_SIZE+5];
bool cmp(BALL x,BALL y)
{
return x.x<y.x;
}
long long n,sx;
long long f[_SIZE+5][_SIZE+5],g[_SIZE+5][_SIZE+5];
long long sum[_SIZE+5];
long long SumCount(long long l,long long r) {return sum[r]-sum[l-1];}
long long ans=0;
int main()
{
mem(f,0x7f);
mem(g,0x7f);
read(n),read(sx);
for (long long i=1;i<=n;i++) read(ball[i].x);
for (long long i=1;i<=n;i++) {read(ball[i].y);ans+=ball[i].y;}
for (long long i=1;i<=n;i++) read(ball[i].v);
n++;ball[n].x=sx;
sort(ball+1,ball+n+1,cmp);
for (long long i=1;i<=n;i++) sum[i]=ball[i].v+sum[i-1];
for (long long i=1;i<=n;i++) if (ball[i].x==sx) f[i][i]=g[i][i]=0;
for (long long len=2;len<=n;len++)
{
for (long long i=1;i+len-1<=n;i++)
{
long long j=i+len-1;
f[i][j]=min(f[i][j],f[i+1][j]+(SumCount(1,i)+SumCount(j+1,n))*(ball[i+1].x-ball[i].x));
f[i][j]=min(f[i][j],g[i+1][j]+(SumCount(1,i)+SumCount(j+1,n))*(ball[j].x-ball[i].x));
g[i][j]=min(g[i][j],f[i][j-1]+(SumCount(1,i-1)+SumCount(j,n))*(ball[j].x-ball[i].x));
g[i][j]=min(g[i][j],g[i][j-1]+(SumCount(1,i-1)+SumCount(j,n))*(ball[j].x-ball[j-1].x));
}
}
printf("%.3lf\n",(double)(ans-min(g[1][n],f[1][n]))/1000);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步