CodeForces 704B Ant Man
https://codeforces.com/problemset/problem/704/B
Tutorial
https://blog.sengxian.com/solutions/cf-704b
发现 (i) 的贡献只与 (i,j) 的相对大小有关, (j) 的贡献亦然.
我们要求就是一条从 (s) 到 (e) 的链,想要用DP来解决这个问题.
那么很容易想到,DP状态和当前联通块链的个数有关.
有 (3) 种链
- 包含 (s) 的链
- 包含 (t) 的链
- 其他链
设 (dp(i,j,u,v)) 表示 ([1,i]) 这些点中,3,1,2种链的个数为 (j,u,v) 时的最小值,转移就是向这个图中加入 (i+1) 这个点的位置
- 单独成链
- 一个链前方
- 一个链后方
- 连接两个链
当 (i+1=s,e) 时特殊处理一下即可.
Code
#include <cstdio>
#include <cstring>
#include <iostream>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
inline char nc() {
// return getchar();
static char buf[100000],*l=buf,*r=buf;
return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x) {
x=0; int f=1,ch=nc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
x*=f;
}
template<class T> inline bool Cmin(T &x,T y) {return x>y?x=y,1:0;}
typedef long long ll;
const ll INF=1e18;
const int maxn=5000+5;
int n,s,e,x[maxn],a[maxn],b[maxn],c[maxn],d[maxn];
ll f[2][maxn][2][2];
int main() {
read(n),read(s),read(e);
for(int i=1;i<=n;++i) read(x[i]);
for(int i=1;i<=n;++i) read(a[i]),a[i]+=x[i];
for(int i=1;i<=n;++i) read(b[i]),b[i]-=x[i];
for(int i=1;i<=n;++i) read(c[i]),c[i]+=x[i];
for(int i=1;i<=n;++i) read(d[i]),d[i]-=x[i];
int cur=0;
for(int u=0;u<2;++u) for(int v=0;v<2;++v) f[cur][0][u][v]=INF;
f[cur][0][0][0]=0;
for(int i=1;i<=n;++i) {
cur^=1;
for(int j=0;j<=i;++j) for(int u=0;u<2;++u) for(int v=0;v<2;++v) f[cur][j][u][v]=INF;
for(int j=0;j<i;++j) for(int u=0;u<2;++u) for(int v=0;v<2;++v) if(f[cur^1][j][u][v]!=INF) {
if(i==s) {
if(j) Cmin(f[cur][j-1][1][v],f[cur^1][j][u][v]+c[i]);
Cmin(f[cur][j][1][v],f[cur^1][j][u][v]+d[i]);
if(i==n) Cmin(f[cur][j][0][0],f[cur^1][j][u][v]+c[i]);
}
else if(i==e) {
if(j) Cmin(f[cur][j-1][u][1],f[cur^1][j][u][v]+a[i]);
Cmin(f[cur][j][u][1],f[cur^1][j][u][v]+b[i]);
if(i==n) Cmin(f[cur][j][0][0],f[cur^1][j][u][v]+a[i]);
}
else {
if(j||v) Cmin(f[cur][j][u][v],f[cur^1][j][u][v]+b[i]+c[i]);
if(j||u) Cmin(f[cur][j][u][v],f[cur^1][j][u][v]+a[i]+d[i]);
if(j>1||(j&&(u||v))) Cmin(f[cur][j-1][u][v],f[cur^1][j][u][v]+a[i]+c[i]);
Cmin(f[cur][j+1][u][v],f[cur^1][j][u][v]+b[i]+d[i]);
if(i==n) Cmin(f[cur][j][0][0],f[cur^1][j][u][v]+a[i]+c[i]);
}
}
}
printf("%lld
",f[cur][0][0][0]);
return 0;
}