HDU 5699 货物运输

点击打开链接


题解:(备注:其实有博客这个题目的题解写的很好,我随便写的有点乱,我想记录的是我wa的原因,还有为什么思路是这个?这些想法都在代码的后面)

因为题目是在一个区间里面找到一个数(0—n),而且其实只要时间t越大,t是可以满足所有的运输方案都能在t时间内完成。

所以我们要找的是最大值中的最小值~ 所以可以用二分做,而且有点像二分里的二分法求下界的感觉。

二分下界是按照紫书的算法模型理解的。~

问题在于if的条件判断。

对于每一个li和ri,(令r >= l)

如果   ri - li ≤ mid ,他可以不用传送器~

如果 大于 ,那么设传送器为x , y ( x >= y)

则 | ri - x | - | ri - y | <= mid.

把它拆成四个不等式即可以知道 x+y 与 y-x 的范围

     l+r-mid<= x+y <=l+r+mid;

     r-l-mid<=y-x<=r-l+mid;

那么if的条件成立就是  对于所有的(划重点)需要传送器的点而言,x+y和y-x都可以算出解来。

那么x+y的最大值l+r-mid就是所有需要传送器的点的这个值的最小值。

即 max1=min(max1,l+r+mid);

同理 x+y的最小值 min1=max(min1 , l+r-mid);  y-x的最小值min2=max(min2 , r-l-mid) ; max2=min(max2, r-l+mid);

那么为了有解可得,则 x+y的最小值的最大值(max1)要 小于等于 最大值的最小值(min1);

x-y的最小值的最大值(max2) 要小于等于 最大值的最小值(min2);


AC代码:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <stack>
#define pie ((long double)acos(-1))
#define max(x1,x2) ((x1)>(x2)?(x1):(x2))
#define min(x1,x2) ((x1)<(x2)?(x1):(x2))
using namespace std;
const int maxn=10e6+10;
int n,m;
int L,R,mid;
int l[maxn],r[maxn];

bool check(int mid)
{
    int maxx1=0x7fffffff;
    int maxx2=0x7fffffff;
    int minn1=-0x7fffffff;
    int minn2=-0x7fffffff;
    for(int i=0;i<m;i++)
    {
        if(r[i]-l[i]>mid){
             maxx1=min(l[i]+r[i]+mid,maxx1);
             minn1=max(l[i]+r[i]-mid,minn1);
             maxx2=min(r[i]-l[i]+mid,maxx2);
             minn2=max(r[i]-l[i]-mid,minn2);
        }

    }
    int flag=0;
    if(maxx1>=minn1 && maxx2>=minn2)
    {
        flag=1;
        if(maxx1==minn1&& maxx2==minn2 )
           {
               if((maxx1+maxx2)%2==1)
                  flag=0;
           }

    }
    if(flag==0) return false;
    else return true;
}

int main()
{
    while(cin>>n>>m)
    {
        for(int i=0;i<m;i++)
      {
          scanf("%d%d",&l[i],&r[i]);
          if(l[i]>r[i])
          {
              int temp=l[i];
              l[i]=r[i];
              r[i]=temp;
          }
      }
      //二分
      L=0;
      R=n;
      mid=0;
      while(L<R)
      {
          mid=L+(R-L)/2;
          if(check(mid)) R=mid;
          else L=mid+1;
      }
      cout<<L<<endl;
    }

    return 0;
}

上面写的思路和AC代码有一点点不一样,思路是能过的.要是看了别的博客肯定知道为啥弄个flag了。


我想补充的是:

1.我们为什么要通过x+y ,y-x的范围来判断二分? 实际上其实我们是想知道 当mid等于当前值的时候,我们能不能找到(至少)一对x,y来构建传送器。

当然我们可以求出x,y但是其实没必要算出来,而且很麻烦QAQ

2.强调是“所有的(划重点)需要传送器的点而言,x+y和y-x都可以算出解来”,我一开始先通过四个不等式直接算出x和y的不等式(而不是x+y和x-y),

结果是错的就是因为考虑不对。

3.

if(r[i]-l[i]>mid)
这句我本来觉得> 和>=是差不多的,因为如果刚好可以使用传送器何乐而不为呢,但是后来wa了。。。。

我举了例子想了想是因为,当r-l=mid时,你拿l和r去算max和min,可能会使x,y的范围变苛刻,这样可能真正需要传送器的点结果用不了传送器了。

所以不能写等号~

4.题目是“多组数据”。。。。。我没仔细看QAQ 题目写得好精练???QAQ



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值