【题解】[SDOI2008]Sue的小球

[SDOI2008]Sue的小球

( ext{Solution:})

长得很像区间 (dp) 对吧,那猜的也差不多了。

注意到有一个全局的总时间对答案造成影响,考虑把它给计算进 (dp) 值里面。

也就是 (2009) 年论文说到的:

费用提前计算

其实是一个很简单的套路:把每一次转移消耗的时间造成的损耗加进 (dp) 值里面,这就可以省去 (dp) 状态中的时间这个维度了。

所以自然设计出状态: (dp[l][r][0/1]) 表示完成区间 ([l,r]) 内所有球,且当前人在左边/右边的最大价值。

转移直接看代码吧,比较显然。

细节要注意:原来的错误原因是因为在 int 类型下把最大值设为了 (2^{31}-1) 导致运算的时候自然溢出导致错误,开 long long 就对了。

错误特征:会输出一个和你设计的 (dp) 数组赋给的最值相反符号的数。

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int MAXN=1.5e3+10;
const db eps=1e-10;
const int dyx=1LL<<50;
namespace DyxAkIOI {
	int n,pos,sum[MAXN];
	struct point {
		int x,y,v;
		point(){x=0;y=0;v=0;}
		bool operator<(const point&B)const{
			return x<B.x;
		}
	} p[MAXN];
	int sumv[MAXN];
	int f[MAXN][MAXN][2];
	inline int Max(int x,int y){return x>y?x:y;}
	inline int Min(int x,int y){return x<y?x:y;}
	inline int read() {
		int s=0,w=1;
		char ch=getchar();
		while(!isdigit(ch)) {
			if(ch=='-')w=-1;
			ch=getchar();
		}
		while(isdigit(ch)) {
			s=s*10-48+ch;
			ch=getchar();
		}
		return s*w;
	}
	int getspeed(int l,int r){
		return sumv[r]-sumv[l-1];
	}
	void Init() {
		n=read();
		pos=read();
		for(int i=1;i<=n;++i)p[i].x=read();
		for(int i=1;i<=n;++i)p[i].y=read();
		for(int i=1;i<=n;++i)p[i].v=read();
		p[++n].x=pos;
		sort(p+1,p+n+1);
		int P;
		for(int i=1;i<=n;++i){
			sumv[i]=sumv[i-1]+p[i].v;
			if(p[i].x==pos)P=i;
		}
		for(int i=0;i<=n+1;++i)
			for(int j=0;j<=n+1;++j)
				f[i][j][0]=f[i][j][1]=-dyx;
		f[P][P][0]=0;f[P][P][1]=0;
		for(int len=2;len<=n;++len){
			for(int l=1;l<=n-len+1;++l){
				int r=l+len-1;
				f[l][r][0]=p[l].y+Max(f[l+1][r][1]-(sumv[n]-getspeed(l+1,r))*(p[r].x-p[l].x),f[l+1][r][0]-(sumv[n]-getspeed(l+1,r))*(p[l+1].x-p[l].x));
				f[l][r][1]=p[r].y+Max(f[l][r-1][0]-(sumv[n]-getspeed(l,r-1))*(p[r].x-p[l].x),f[l][r-1][1]-(sumv[n]-getspeed(l,r-1))*(p[r].x-p[r-1].x));
			}
		}
//		cout<<Max(f[1][n][0],f[1][n][1])<<endl;
//		for(int i=1;i<=n;++i)
//			for(int j=1;j<=n;++j)
//				printf("%d %d %c",f[i][j][0],f[i][j][1],j==n?'
':' ');
		printf("%.3lf
",(double)(Max(f[1][n][0],f[1][n][1]))/1000.0);
	}
}

signed main() {
//	freopen("111.txt","r",stdin);
	DyxAkIOI::Init();
	return 0;
}
原文地址:https://www.cnblogs.com/h-lka/p/14995374.html