洛谷P9676 [ICPC 2022 Jinan R] Skills

洛谷P9676 [ICPC 2022 Jinan R] Skills

P9676 [ICPC 2022 Jinan R] Skills

设计状态时,可以知道要用当前的压掉一维,\(dp_{i,j,0/1/2}\) 表示当前选第 \(0/1/2\) 种,\(i,j\) 表示其余两种的最后选择时间。

如果没有 \(0\) 的限制,我们可以很自然的看出 \(DP\) 方程。

首先,上次选的,这次也选。

// cur表示时间,now是cur&1
dp[now^1][i][j][0] = max(dp[now^1][i][j][0],dp[now][i][j][0]-(i?cur-i+1:0)-(j?cur-j+1:0)+val[cur+1][0]);
dp[now^1][i][j][1] = max(dp[now^1][i][j][1],dp[now][i][j][1]-(i?cur-i+1:0)-(j?cur-j+1:0)+val[cur+1][1]);
dp[now^1][i][j][2] = max(dp[now^1][i][j][2],dp[now][i][j][2]-(i?cur-i+1:0)-(j?cur-j+1:0)+val[cur+1][2]);

然后,上次选的,这次不选,一共 \(9\) 种。

dp[now^1][cur][j][1] = max(dp[now^1][cur][j][1],dp[now][i][j][0]-(j?cur-j+1:0)-1+val[cur+1][1]);
dp[now^1][cur][i][2] = max(dp[now^1][cur][i][2],dp[now][i][j][0]-(i?cur-i+1:0)-1+val[cur+1][2]);
dp[now^1][cur][j][0] = max(dp[now^1][cur][j][0],dp[now][i][j][1]-(j?cur-j+1:0)-1+val[cur+1][0]);
dp[now^1][i][cur][2] = max(dp[now^1][i][cur][2],dp[now][i][j][1]-(i?cur-i+1:0)-1+val[cur+1][2]);
dp[now^1][j][cur][0] = max(dp[now^1][j][cur][0],dp[now][i][j][2]-(j?cur-j+1:0)-1+val[cur+1][0]);
dp[now^1][i][cur][1] = max(dp[now^1][i][cur][1],dp[now][i][j][2]-(i?cur-i+1:0)-1+val[cur+1][1]);

再来一个性质,一个练习不可能掉成 \(0\),否则不如一开始就给其他练习。

距离上一次不会超过 \(200\) 天。

做完了,时复 \(O(n\max{a_{i,j}})\)

\(\Large \mathscr{Code}\)

#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
int T,n,m,val[N][4],dp[2][N][N][3],ans;
inline void DP(int cur,int i,int j){
	int now = cur&1;
	dp[now^1][i][j][0] = max(dp[now^1][i][j][0],dp[now][i][j][0]-(i?cur-i+1:0)-(j?cur-j+1:0)+val[cur+1][0]);
	dp[now^1][i][j][1] = max(dp[now^1][i][j][1],dp[now][i][j][1]-(i?cur-i+1:0)-(j?cur-j+1:0)+val[cur+1][1]);
	dp[now^1][i][j][2] = max(dp[now^1][i][j][2],dp[now][i][j][2]-(i?cur-i+1:0)-(j?cur-j+1:0)+val[cur+1][2]);
	dp[now^1][cur][j][1] = max(dp[now^1][cur][j][1],dp[now][i][j][0]-(j?cur-j+1:0)-1+val[cur+1][1]);
	dp[now^1][cur][i][2] = max(dp[now^1][cur][i][2],dp[now][i][j][0]-(i?cur-i+1:0)-1+val[cur+1][2]);
	dp[now^1][cur][j][0] = max(dp[now^1][cur][j][0],dp[now][i][j][1]-(j?cur-j+1:0)-1+val[cur+1][0]);
	dp[now^1][i][cur][2] = max(dp[now^1][i][cur][2],dp[now][i][j][1]-(i?cur-i+1:0)-1+val[cur+1][2]);
	dp[now^1][j][cur][0] = max(dp[now^1][j][cur][0],dp[now][i][j][2]-(j?cur-j+1:0)-1+val[cur+1][0]);
	dp[now^1][i][cur][1] = max(dp[now^1][i][cur][1],dp[now][i][j][2]-(i?cur-i+1:0)-1+val[cur+1][1]);
}
inline void work(){
	cin>>n;
	ans = 0;
	for(int i=1;i<=n;i++){
		cin>>val[i][0]>>val[i][1]>>val[i][2];
	}
	memset(dp,-0x3f,sizeof(dp));
	dp[0][0][0][0] = dp[0][0][0][1] = dp[0][0][0][2] = 0;
	for(int cur=0;cur<n;cur++){
		int now = cur&1;
		for(int i=max(0,cur-201);i<=cur;i++){
			for(int j=max(0,cur-201);j<=cur;j++){
				memset(dp[now^1][i][j],-0x3f,sizeof(dp[now^1][i][j]));
			}
		}
		for(int i=max(0,cur-201);i<=cur;i++){
			memset(dp[now^1][0][i],-0x3f,sizeof(dp[now^1][0][i]));
		}
		for(int i=max(0,cur-201);i<=cur;i++){
			memset(dp[now^1][i][0],-0x3f,sizeof(dp[now^1][i][0]));
		}
		memset(dp[now^1][0][0],-0x3f,sizeof(dp[now^1][0][0]));
		for(int i=max(0,cur-201);i<=cur;i++){
			for(int j=max(0,cur-201);j<=cur;j++){
				DP(cur,i,j);
			}
		}
		for(int i=max(0,cur-201);i<=cur;i++){
			DP(cur,0,i);
		}
		for(int i=max(0,cur-201);i<=cur;i++){
			DP(cur,i,0);
		}
		DP(cur,0,0);
	}
	for(int i=0;i<=n;i++){
		for(int j=0;j<=n;j++){
			ans = max({ans,dp[n&1][i][j][0],dp[n&1][i][j][1],dp[n&1][i][j][2]});
		}
	}
	cout<<ans<<'\n';
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>T;
	while(T--) work();
	return 0;
}

posted @ 2025-10-05 08:14  OrangeRED  阅读(10)  评论(0)    收藏  举报