CF1057C Tanya and Colored Candies
Description
给定一个长度为 \(n\) 的序列,第 \(i\) 个点的价值为 \(r_i\) ,颜色为R,B,G其中的一种。
你的初始位置是 \(s\) ,向左或右移动一步需要花费 \(1\) 的时间,但是收集某个点的价值不需要时间。
要求是收集点的时候前后两个点的颜色不一样,并且当前点的价值要大于上一个点。
请问收集价值至少为 \(k\) 的最小时间。
Solution
发现 \(n\leq 50\) ,那么可以瞎搞设计一个DP。
设 \(f_{i,j}\) 表示到第 \(i\) 个位置收集了 \(j\) 的最小时间。
那么,初始状态为 \(f_{i,r_i}=|i-s|\) ,转移方程为:
\[f_{k,j+r_k}=\min_i^{col_i\not =col_k,r_i<r_k}(f_{k,j+r_k},f_{i,j}+|i-k|)
\]
注意:因为是至少 \(k\) 的价值,而 \(r_i\leq 50\) ,所以要枚举 \(1\) 到 \(k+50\) 。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=110,INF=0x3f3f3f3f;
int n,s,m,ans=INF,r[N],f[N][3010];
char col[N];
int main(){
scanf("%d%d%d",&n,&s,&m);
for(int i=1;i<=n;i++)
scanf("%d",&r[i]);
scanf("%s",ch+1);
memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++)
f[i][r[i]]=abs(i-s);
for(int j=1;j<=m+50;j++)
for(int i=1;i<=n;i++)
for(int k=1;k<=n;k++)
if(col[i]!=col[k]&&r[i]<r[k]) f[k][j+r[k]]=min(f[k][j+r[k]],f[i][j]+abs(i-k));
for(int i=1;i<=n;i++)
for(int j=m;j<=m+50;j++)
ans=min(ans,f[i][j]);
if(ans==INF) puts("-1");
else printf("%d\n",ans);
return 0;
}