一眼丁真,鉴定为 原题。
现将所有点按照 \(x\) 排序,区间 \([l,r]\) 的终点一定是 \(l\) 或 \(r\),否则会跑冤枉路。
设 \(f_{i,j,0/1}\) 表示在区间 \([i,j]\) 最终落在 左端点
/ 右端点
的最大价值。
但这样是寄的,这个 DP 有后效性,当前花费的时间会对之后产生影响,小球的贡献跟时间有关。
考虑区间 \([i,j]\) 中 \(i\) 的贡献 \(\left(y_i-v_it\right)\),\(t\) 表示之前决策的时间总和,是不是说明我们可以把 \(v_it\) 这个量在 DP 过程中进行计算?
具体的,我们每一动一次,都会把未来减少的得分 \(v_it\) 计算在内,比如对于一个状态 \((i-1,j,0)\),转移到 \((i,j,0)\),我们不光要计算 \(i\) 的贡献,还要将其它所有正在下落的小球的贡献计算上。
我们可以用一个前缀和 \(s_i\) 表示某一个区间下落速度之和,即令 \(s_{i,j}\leftarrow V-\sum \limits_{k=i}^j v_k\)。其中 \(V\) 表示所有小球的下落速度之和。
那么我们可以得到状态转移方程:
\[\begin{cases} f_{i,j,0}\leftarrow y_i+\max\{f_{i+1,j,0}-s_{i+1,j}\left(x_{i+1}-x_{i}\right),f_{i+1,j,1}-s_{i+1,j}\left(x_{j}-x_i\right)\} \\ f_{i,j,1}\leftarrow y_j+\max\{f_{i,j-1,0}-s_{i,j-1}\left(x_j-x_i\right),f_{i,j-1,1}-s_{i,j-1}\left(x_j-x_{j-1}\right)\} \end{cases} \]初始值:\(f_{i,i,0/1}\leftarrow y_i+V |x0-x_i|\)。
时间复杂度 \(\Theta(n^2)\),可以通过本题。
代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define rev(i,a,b) for(register int i=a;i>=b;--i)
#define gra(i,u) for(register int i=head[u];i;i=edge[i].nxt)
#define Clear(a) memset(a,0,sizeof(a))
#define yes puts("YES")
#define no puts("NO")
using namespace std;
typedef long long ll;
const int INF(1e9+10);
const ll LLINF(1e18+10);
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+(ch-'0'),ch=getchar();
return s*w;
}
template<typename T>
inline T Min(T x,T y){return x<y?x:y;}
template<typename T>
inline T Max(T x,T y){return x>y?x:y;}
template<typename T>
inline void Swap(T&x,T&y){T t=x;x=y;y=t;return;}
template<typename T>
inline T Abs(T x){return x<0?-x:x;}
const int MAXN(1010);
int n,x0;
struct node{int x,y,v;};
node a[MAXN];
ll f[MAXN][MAXN][2],V,sum[MAXN];
inline bool cmp(node x,node y){return x.x<y.x;}
inline ll s(int x,int y){return V-(sum[y]-sum[x-1]);}
int main()
{
// freopen("read.txt","r",stdin);
memset(f,~0x7f,sizeof(f));
n=read(),x0=read();
rep(i,1,n) a[i].x=read();
rep(i,1,n) a[i].y=read();
rep(i,1,n) a[i].v=read(),V+=a[i].v;
a[++n].x=x0;
sort(a+1,a+1+n,cmp);
rep(i,1,n) sum[i]=sum[i-1]+a[i].v;
rep(i,1,n) f[i][i][0]=f[i][i][1]=a[i].y-1ll*Abs(x0-a[i].x)*V;
rep(d,2,n) rep(i,1,n-d+1)
{
int j=i+d-1;
f[i][j][0]=a[i].y+Max(f[i+1][j][0]-1ll*s(i+1,j)*(a[i+1].x-a[i].x),f[i+1][j][1]-s(i+1,j)*1ll*(a[j].x-a[i].x));
f[i][j][1]=a[j].y+Max(f[i][j-1][0]-1ll*s(i,j-1)*(a[j].x-a[i].x),f[i][j-1][1]-s(i,j-1)*1ll*(a[j].x-a[j-1].x));
}
printf("%.3lf\n",Max(f[1][n][0],f[1][n][1])/1000.0);
return 0;
}
/*
Date : 2022/9/6
Author : UperFicial
Start coding at : 8:30
finish debugging at : 9:00
*/
标签:ch,int,题解,include,P2466,right,inline,SDOI2008,define
From: https://www.cnblogs.com/UperFicial/p/16660554.html