【问题背景】

zhx 为他的妹子造了一幢摩天楼。

【问题描述】

zhx 有一幢摩天楼。 摩天楼上面有 M 个观光电梯,每个观光电梯被两个整数u " ,d " 描述。每个电梯只有两个按钮, (针对第 i 个电梯)两个按钮分别可以使

电梯向上u" 层向下d" 层。摩天楼的高度是无限的,但是电梯不可以钻入地下,

也就是说是有下限的。每层楼用整数标记, 以 0 作为地面这一层的标记。

zhx 去陪他妹子了,留你一个人在摩天楼的 0 层,现在你想知道,仅可以选择 M 个电梯中的一个乘坐(不可以中途换电梯) ,按电梯中的按钮 N 次后(每次两个按钮选一个按) ,可以到达的最低楼层数。按电梯的过程中请注意,如果当前所在楼层数小于你选择的d" ,你将无法选择电梯向下运行。

【输入格式】

第一行两个数 N 和 M,如题目描述。

接下来 M 行,每行两个整数d " 和u " 。

【输出格式】

仅一行一个整数,包含所求的答案。

【样例输入】

10 3

15 4

15 12

7 12

【样例输出】

13

【数据范围与规定】

对50%的数据,所有1≤N,M≤1000。

对于100%的数据,所有1≤N≤10^7,1≤M≤2000,1≤u, d≤10^5 。

分析:
  思路题,想想就想出来了
  很容易想到n*m的做法,就是对于每个i枚举一个合适的j,使上升和下降的差值最小,然后我们可以把这个j算出来,省去第二维循环。
代码:
#include<cstdio>
#include<iostream>
#define ll long long
#define M 2010
#define INF 10000000000000LL
using namespace std;
ll up[M],down[M],n,m,ans=INF;
ll read()
{
    ll num=0,flag=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*flag;
}
int main()
{
    //freopen("jh.in","r",stdin);
    freopen("building.in","r",stdin);
    freopen("building.out","w",stdout);
    n=read();m=read();
    for(ll i=1;i<=m;i++)
      up[i]=read(),down[i]=read();
    for(ll i=1;i<=m;i++)
    {
        ll uc=(down[i]*n)/(down[i]+up[i]);
        ll dc=n-uc;
        for(ll j=-1;j<=1;j++)
          if(uc+j>=0&&dc-j>=0&&(uc+j)*up[i]-(dc-j)*down[i]>=0)
            ans=min(ans,(uc+j)*up[i]-(dc-j)*down[i]);
    }
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/harden/p/5962173.html