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

博客给出一道题的题解,提到可采用二分答案结合时间逆流的方法,转化为经典路灯问题。也可不使用二分答案,倒着考虑是先走旁边再走中间,还需计算到当前点加下课时间的最小时间,代码有一个点未通过且对拍未找出问题。

题解:

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

这样就变成了经典的路灯问题 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=1100;
const int INF=1e9;
int n,m,k;
int f[N],g[N][N][2],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=0;
  rep(i,1,m)
  {
    cin>>a[i].a>>a[i].b;
  }
  sort(a+1,a+m+1,cmp);
  a[0].a=INF;
  int cnt=0;
  rep(i,1,m)
  {
    if (a[i].a!=a[i-1].a) cnt++;
    f[cnt]=max(f[cnt],a[i].b);
    p[cnt]=a[i].a;
  }
  maxa=cnt+1; p[maxa]=p[maxa-1];
  rep(i,0,N-1)
    rep(j,0,N-1) g[i][j][0]=g[i][j][1]=INF;
  g[0][maxa][0]=0;
  dep(i,maxa,0)
    rep(j,0,maxa-i)
    {
      rint k=j+i;
      if (g[j][k][0]!=INF)
        minn(g[j+1][k][0],max(g[j][k][0]+p[j+1]-p[j],f[j+1])),
        minn(g[j][k-1][1],max(g[j][k][0]+p[k-1]-p[j],f[k-1]));
      if (g[j][k][1]!=INF )
        minn(g[j][k-1][1],max(g[j][k][1]+p[k]-p[k-1],f[k-1])),
        minn(g[j+1][k][0],max(g[j][k][1]+p[k]-p[j+1],f[j+1]));
    }
  int ans=INF;
  rep(i,0,maxa)
    ans=min(ans,abs(p[i]-k)+min(g[i][i][1],g[i][i][0]));
  cout<<ans<<endl;
  return 0;
}

 

转载于:https://www.cnblogs.com/yinwuxiao/p/9551814.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值