【BZOJ3379】[Usaco2004 Open]Turning in Homework 交作业

时间:2021-08-10 13:19:56

题解:

比较容易想到二分答案+时间逆流

这样就变成了经典的路灯问题 f[a][b][0/1]

其实可以不用二分答案

根据倒着考虑我们会发现一定是先走旁边的再走中间的

计算到当前点+下课时间所需的最小时间

代码:

神奇的wa了一个点 对拍并不能拍出来

#include <bits/stdc++.h>
using namespace std;
#define rint int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
#define ll long long
const int N=;
const int INF=1e9;
int n,m,k;
int f[N],g[N][N][],maxa,p[N];
IL void minn(rint& x,rint y)
{
if (x>y) x=y;
}
struct re{
int a,b;
}a[N];
IL bool cmp(re x,re y)
{
return x.a<y.a;
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n>>m>>k;
int maxa=;
rep(i,,m)
{
cin>>a[i].a>>a[i].b;
}
sort(a+,a+m+,cmp);
a[].a=INF;
int cnt=;
rep(i,,m)
{
if (a[i].a!=a[i-].a) cnt++;
f[cnt]=max(f[cnt],a[i].b);
p[cnt]=a[i].a;
}
maxa=cnt+; p[maxa]=p[maxa-];
rep(i,,N-)
rep(j,,N-) g[i][j][]=g[i][j][]=INF;
g[][maxa][]=;
dep(i,maxa,)
rep(j,,maxa-i)
{
rint k=j+i;
if (g[j][k][]!=INF)
minn(g[j+][k][],max(g[j][k][]+p[j+]-p[j],f[j+])),
minn(g[j][k-][],max(g[j][k][]+p[k-]-p[j],f[k-]));
if (g[j][k][]!=INF )
minn(g[j][k-][],max(g[j][k][]+p[k]-p[k-],f[k-])),
minn(g[j+][k][],max(g[j][k][]+p[k]-p[j+],f[j+]));
}
int ans=INF;
rep(i,,maxa)
ans=min(ans,abs(p[i]-k)+min(g[i][i][],g[i][i][]));
cout<<ans<<endl;
return ;
}