Description
给定一个长度为 (n) 的序列,第 (i) 个点的价值为 (r_i) ,颜色为R,B,G其中的一种。
你的初始位置是 (s) ,向左或右移动一步需要花费 (1) 的时间,但是收集某个点的价值不需要时间。
要求是收集点的时候前后两个点的颜色不一样,并且当前点的价值要大于上一个点。
请问收集价值至少为 (k) 的最小时间。
Solution
发现 (nleq 50) ,那么可以瞎搞设计一个DP。
设 (f_{i,j}) 表示到第 (i) 个位置收集了 (j) 的最小时间。
那么,初始状态为 (f_{i,r_i}=|i-s|) ,转移方程为:
[f_{k,j+r_k}=min_i^{col_i
ot =col_k,r_i<r_k}(f_{k,j+r_k},f_{i,j}+|i-k|)
]
注意:因为是至少 (k) 的价值,而 (r_ileq 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
",ans);
return 0;
}