您的位置:首页 > 其它

【Code Forces 320C】【贪心+讨论】A Problem about Polyline 点在折线段上求最小的波浪长度

2015-09-17 15:50 197 查看
【传送门】

http://codeforces.com/contest/579/problem/C

【题意】

给你一段波浪线,点数变化情况是——

(0,0)->(x,x)->(2x,0)->(3x,x)

也就是,先以1的斜率递增长度x,再以-1的斜率递减长度x,

再给你一个点(a,b),让你输出尽可能小的x,使得(a,b)在这样的折线上。

【类型】

贪心+讨论

【分析】

首先x>=b是一定的,

然后为了方便,我们把(a,b)映射到x轴上

我们不知道(a,b)是在上升段还是下降段,

所以映射有两种——

(1)a-=b;

(2)a+=b;

然后a就是横坐标了

而不管a是-=b还是+=b,现在的a肯定都将是2x的整数倍,我们是希望使得x尽可能小,也就是这个倍数尽可能大。

然而这里有一个限定条件,x>=b

所以我们假定x=b,这种情况下x最小,倍数也会尽可能大。

于是我们求出这个倍数(因为要求是整数),然后再求出其对应的x,并更新答案。

【时间复杂度&&优化】

O(1)

这题的标程,代码只有2行——

[code]if(a<b)puts("-1");
else printf("%.12f\n",(a+b)/(2.*((a+b)/(2*b))));


咦,其实和我之前写的代码一样,但是简化了,不用再考虑a-b

为什么呢?

因为可以总结为——

一定是把这个点向最右端映射才最优。

为什么呢?

首先不论向左还是向右映射,都是恰好要求是2kx的位置,

然后x是有最小值的,所以我们能求得k的最大值,并且向下取整得到最大可能的整数k。

然后答案的映射是

k1=[(a-b)/(2b)]

k2=[(a+b)/(2b)]

v1=(a-b)/k1

v2=(a+b)/k2

k2一定比k1大1

而且k2/k1 >= (a+b)/(a-b) (分母与分子差固定,分母与分子越接近数值就越大)

于是在(a-b)/k1与(a+b)/(k1+1)的大小比较的时候

必然有(a-b)/k1 >= (a+b)/k2

取(a+b)/k2即可,于是就有了2行代码的标程

【trick】

然而这道题有一个点比较特殊,就是——

我们算出倍数k之后,有if(k)gmin(ans,lft/(2.0*k));

因为涉及到除法,所以这里k必须要求是整数。

然而k是可能为0而且合法的,这种情况出现在a=b的时候,有的写法会在这里卡住,特判一下即可

【数据】

Input

3 1

Output

1.000000000000

Input

1 3

Output

-1

Input

4 1

Output

1.250000000000

【代码】

[code]#include<stdio.h>
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional>
#include<string>
#include<algorithm>
#include<time.h>
#include<bitset>
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=0,M=0,Z=1e9+7,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;const double eps=1e-8,PI=acos(-1.0);//.0
int a,b;
int main()
{
    while(~scanf("%d%d",&a,&b))
    {
        int x=a+b;
        int k=x/(b<<1);
        if(k)printf("%.12f\n",x/(2.0*k));
        else printf("-1\n");
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: