luogu5052 GO 题解

分析

这题评紫确实过了。很容易看出来是套路的区间 DP。

\(f(i,j,t,0/1)\) 表示抓到了区间 \([i,j]\) 的宝可梦,花费的时间为 \(t\),在 \(i\)\(j\) 的位置,所获得的最大收益。

转移情况比较多,用刷表法比较方便,而且要注意时间限制,否则下面的 \(B\) 是不能加的。 \[ f(i-1,j,t +\Delta t,0) = \max \begin{cases} f(i,j,t,0) + B_{i-1} \\ f(i,j,t,1) + B_{i-1} \end{cases} \]

\[ f(i,j+1,t +\Delta t,1) = \max \begin{cases} f(i,j,t,0) + B_{j+1} \\ f(i,j,t,1) + B_{j+1} \end{cases} \]

计算 \(\Delta t\) 只需要将对应的编号相减就行了。

注意状态中的 \([i,j]\) 指的是按照编号排序后排名为 \([i,j]\) 的宝可梦,而不是房子编号,不然复杂度不对。这一步就相当于离散化。

边界为

\[ f(i,j,t,0/1) = \begin{cases} 0 & i=j=k \\ -\infty & \text{otherwise} \end{cases} \]

复杂度 \(O(m^2 \max T)\)

CODE

#include<bits/stdc++.h>
using namespace std;
const int N=105, maxt=2005, inf=0x3f3f3f3f;
int n, m, k, ans, T, f[N][N][maxt][2];
struct qwq { int num, v, t; } a[N];
bool operator<(qwq a,qwq b) { return a.num<b.num; }
int main() {
	scanf("%d%d%d",&n,&k,&m);
	for(int i=1;i<=m;++i) {
		scanf("%d%d%d",&a[i].num,&a[i].v,&a[i].t);
		T=max(T,a[i].t);
	}
	a[++m]=(qwq){k,0,0}; // 原点
	sort(a+1,a+m+1);
	memset(f,-0x3f,sizeof(f));
	int p=0; for(int i=1;i<=m;++i) if(a[i].num==k) { p=i; break; }
	f[p][p][1][1]=f[p][p][1][0]=0;
	for(int t=1;t<=T;++t) for(int len=1;len<=m;++len) for(int i=1;i+len-1<=m;++i) {
		int j=i+len-1;
		if(f[i][j][t][0]!=-inf) {
			if(i!=1) {
				int tt=t+a[i].num-a[i-1].num;
				if(tt<=T) {
					int dlt=0;
					if(tt<=a[i-1].t) dlt=a[i-1].v;
					f[i-1][j][tt][0]=max(f[i-1][j][tt][0],f[i][j][t][0]+dlt);
				}
			}
			if(j!=m) {
				int tt=t+a[j+1].num-a[i].num;
				if(tt<=T) {
					int dlt=0;
					if(tt<=a[j+1].t) dlt=a[j+1].v;
					f[i][j+1][tt][1]=max(f[i][j+1][tt][1],f[i][j][t][0]+dlt);
				}
			}
		}
		if(f[i][j][t][1]!=-inf) {
			if(i!=1) {
				int tt=t+a[j].num-a[i-1].num;
				if(tt<=T) {
					int dlt=0;
					if(tt<=a[i-1].t) dlt=a[i-1].v;
					f[i-1][j][tt][0]=max(f[i-1][j][tt][0],f[i][j][t][1]+dlt);
				}
			}
			if(j!=m) {
				int tt=t+a[j+1].num-a[j].num;
				if(tt<=T) {
					int dlt=0;
					if(tt<=a[j+1].t) dlt=a[j+1].v;
					f[i][j+1][tt][1]=max(f[i][j+1][tt][1],f[i][j][t][1]+dlt);
				}
			}
		}
		ans=max(ans,max(f[i][j][t][0],f[i][j][t][1]));
	}
	printf("%d\n",ans);
}

luogu5052 GO 题解
https://yozora0908.github.io/2022/lg5052-solution/
作者
yozora0908
发布于
2022年4月9日
许可协议