题解:P14424 [JOISC 2014] 邮戳收集 / Collecting Stamps
Aegleseeker_ · · 题解
很帅的题。直接对着列车的移动路径刻画还是太困难了,因为列车可以重复经过一些位置。考虑刻画经过邮戳台的路径的方案,发现总共有四种走法:从上行列车走上去再走下去
注意到如果我们用第三种走法走了上去,那么移动路径会形如:从下行列车往回走几站之后,在前面的一个站选择第四种走法下去,并用上行列车坐回来。如果我们用一对括号去刻画的话,其实就是若这里有一个右括号,则左边必然要存在一个左括号与之匹配!于是我们称第四种走法为左括号、第三种走法为右括号,那么一组合法的邮戳台行走方案其实就是一个合法的括号串中间穿插着一些空的位置(这些位置我们用第一、二种走法即可)。
而括号串是好 dp 的,常见的套路就是记一下前缀还有多少个未匹配的左括号,对于本题我们也是这么干的。令
说一下如何处理列车走一站的代价
复杂度
#include<bits/stdc++.h>
using namespace std;
const int N=3005;
int n,T;
int u[N],v[N],d[N],e[N];
long long f[N][N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>T;
for(int i=1;i<=n;i++){
cin>>u[i]>>v[i]>>d[i]>>e[i];
}
memset(f,0x3f3f3f3f,sizeof(f));
f[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
f[i][j]=min(f[i][j],f[i-1][j-1]+d[i]+v[i]); //"("
}
for(int j=0;j<n;j++){
f[i][j]=min(f[i][j],f[i-1][j+1]+e[i]+u[i]); //")"
}
for(int j=0;j<=n;j++){
f[i][j]=min(f[i][j],f[i-1][j]+u[i]+v[i]);
}
for(int j=1;j<=n;j++){
f[i][j]=min(f[i][j],f[i-1][j]+d[i]+e[i]);
}
for(int j=1;j<=n;j++){
f[i][j]=min(f[i][j],f[i][j-1]+d[i]+v[i]);
}
for(int j=n-1;j>=0;j--){
f[i][j]=min(f[i][j],f[i][j+1]+e[i]+u[i]);
}
for(int j=0;j<=n;j++){
f[i][j]+=2*j*T;
}
}
cout<<f[n][0]+1ll*(n+1)*T;
return 0;
}