P10236 [yLCPC2024] D. 排卡
Question 问题 P10236 [yLCPC2024] D. 排卡
题目大意:给定长度为 \(n(2 \le n \le 1000)\) 的序列 \(a\),每次可以从头或尾选一个数放到序列 \(b\)(选后删除),求\(\displaystyle \sum_{i=1}^{n-1} b_i^{b_{i+1}}\) 的最大值。(我们仅在计算 \(b_i^{b_{i+1}}\) 的时候将得分对 \(998244353\) 取模)。
Analysis 分析
首先思考贪心:(错解)
第一个从最左边或最右边拿,然后贪心第二个从最左边还是最右边使得 \(b_1^{b_2}\) 最大,一直这样贪心下去。很明显是错的。但很明显连样例的过不了,正确性显然不存在。
观察到 \(n\) 的范围较小,发现想复杂了,直接暴力区间 \(DP\) 即可。
Solution
定义 \(f_{l,r,(0,1)}\) 为区间 \([l,r]\) 最后弹掉的是最左边的(0)还是最右边的(1)。
转移方程非常好写:
\[\begin{aligned}
f_{l,r,0}&=\max{\{f_{l+1,r,0}+a_l^{a_{l+1}},f_{l+1,r,1}+a_l^{a_{r}}\}}\\
f_{l,r,1}&=\max{\{f_{l,r-1,0}+a_r^{a_{l}},f_{l,r-1,1}+a_r^{a_{r-1}}\}}
\end{aligned}
\]
对于 \(f_{l,r,0}\) 的转移进行一个详细的讲述,\(f_{l,r,1}\) 同理。
它只能从 \([l+1,r]\) 转移而来,因为他最后踢掉的是最左边的。所以要么是 \(f_{l+1,r,0}+a_l^{a_{l+1}}\) 要么就是 \(f_{l+1,r,1}+a_l^{a_{r}}\).
Code 代码
signed main(){
read(T);
while(T--){
read(n);
for(rint i=1;i<=n;i++) read(a[i]);
for(rint i=1;i<=n;i++) for(rint j=1;j<=n;j++) f[i,j,0]=f[i,j,1]=0;
for(rint len=2;len<=n;len++){
for(rint l=1;l<=(n-len+1);l++){
int r=l+len-1;
f_{l,r,0}=max({f_{l,r,0},f[l+1,r,0]+power(a[l],a[l+1]),f[l+1,r,1]+power(a[l],a[r])});
f_{l,r,1}=max({f_{l,r,1},f[l,r-1,0]+power(a[r],a[l]),f[l,r-1,1]+power(a[r],a[r-1])});
}
}
printf("%lld\n",max(f[1,n,0],f[1,n,1]));
}
return 0;
}