题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2648
有N块合金,每块合金的金银含量不同,现在知道N块合金融合后银的含量,求金的含量范围?
若只有一种金属,假如有两块,其中一块10%,另一块20%,融合之后的范围(10%,20%)
若有两种金属,假如有两块,其中一块金10%银30%,另一块金20%银40%,融合之后的范围金(10%,20%),银(30%,40%)
将银的含量作为Y轴,金的含量为X轴。
则可以连成直线(10,30) (20,40)
若知道合成后银的含量,比如 32%。则,直线 y = 32 与 (10,30) (20,40) 交点的横坐标就是金的含量,这种情况可以唯一确定。
当有N块金属后,平面上N个点可以用一个凸包围住,然后求直线 y = silver 去和凸包求交点,求出x的范围即可。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
#define Maxn 15005
const double eps = 1e-10;
int dcmp(double x) //三态函数
{
if(fabs(x)<eps)//在一定的精度范围内可认为是0
return 0;
return x>0?1:-1;
}
struct Point
{
double x;
double y;
Point() {}
Point(double _x,double _y):x(_x),y(_y) {}
friend Point operator + (Point a,Point b)
{
return Point(a.x+b.x , a.y+b.y);
}
friend Point operator - (Point a,Point b)
{
return Point(a.x-b.x , a.y-b.y);
}
bool operator <(const Point a) const
{
//return dcmp(y-a.y)==-1 || (dcmp(y-a.y)==0 && dcmp(x-a.x)<0);
return y < a.y || y==a.y && x<a.x;
}
}p[Maxn],stack[Maxn];
double det(Point a,Point b) // 叉积,重载叉积函数
{
return a.x*b.y-a.y*b.x;
}
double det(Point a,Point b,Point o) // 叉积
{
return det(a-o,b-o);
}
double det(Point a,Point b,Point c,Point d) // 叉积
{
return det(b-a,d-c);
}
double dot(Point a,Point b) // 点积
{
return a.x*b.x + a.y*b.y;
}
double dot(Point a,Point b,Point o) // 点积
{
return dot(a-o,b-o);
}
//水平序求凸包
int grahamScan(int n)
{
int top = -1;
stack[++top] = p[0];
stack[++top] = p[1];
for(int i=2;i<n;i++)
{
while(top && det(stack[top],p[i],stack[top-1])<=0)
{
top--;
}
stack[++top] = p[i];
}
int midtop = top;
for(int i=n-2;i>=0;i--)
{
while(top>midtop && det(stack[top],p[i],stack[top-1])<=0)
{
top--;
}
stack[++top] = p[i];
}
return top;
}
void solve(int top,double s)
{
vector<double> ans;
for(int i=0;i<top;i++)
{
Point a = stack[i];
Point b = stack[i+1];
Point c;
if(dcmp(a.x-s) == 0)
{
ans.push_back(a.y);
continue;
}
if(dcmp(s-a.x)>0 && dcmp(b.x-s)>0 || dcmp(s-a.x)<0 && dcmp(b.x-s)<0)
{
if(dcmp(a.y-b.y)>0)
{
c = a;
a = b;
b = c;
}
double yy = a.y + (b.y - a.y)*(s-a.x)/(b.x-a.x);
ans.push_back(yy);
}
}
if(ans.size() == 0) printf("0.000 0.000\n");
else
{
sort(ans.begin(),ans.end());
printf("%.3f %.3f\n",ans[0],ans[ans.size()-1]);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n;
double s;
while(scanf(" %d %lf",&n,&s)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf(" %lf",&p[i].x);
}
for(int i=0;i<n;i++)
{
scanf(" %lf",&p[i].y);
}
sort(p,p+n);
int top = grahamScan(n);
solve(top,s);
}
return 0;
}