题目:
https://www.luogu.org/problem/show?pid=1766
刚看到这题时,没有一点思路;
我只能点开了题解(蒟蒻QAQ,没办法);
然后发现,这就是个模拟……我才不会告诉你,我以为是爆搜QWQ
思路:
按终点纵坐标从大到小排序;
但不保证液滴一定落在纵坐标大的上面;
t记录答案,如果存在i可以到j,且j可以到t,说明j在t上面,j就是此时的答案;
总结:
1.与坐标系相关的题需要考虑函数图像……;
2.注意精度;
3.做题前要有完整的规划,知道自己在干什么,要干什么
吃枣药丸
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef double dou;
const int MAXN=10001;
struct hh
{
dou x1,y1,x2,y2;
}ma[MAXN];
dou k[MAXN],b[MAXN];
int n,s;
bool cmp(hh a,hh b)
{
return a.y2>b.y2;
}
void calc()
{
for(int i=1;i<=n;i++)
{
k[i]=(ma[i].y1-ma[i].y2)/(ma[i].x1-ma[i].x2);
b[i]=ma[i].y1-k[i]*ma[i].x1;
}
return;
}
bool under(int i,int j,dou x) //从i落到j;
{
int h1,h2;
if(!i) return true;
h1=k[i]*x+b[i];
h2=k[j]*x+b[j];
if(h1>h2) return true;
else return false;
}
bool include(int i,int j) //i是否在j的范围内;
{
return min(ma[j].x1,ma[j].x2)<ma[i].x2 && max(ma[j].x1,ma[j].x2)>ma[i].x2;
}
void solve()
{
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&ma[i].x1,&ma[i].y1,&ma[i].x2,&ma[i].y2);
if(ma[i].y1<ma[i].y2) swap(ma[i].x1,ma[i].x2),swap(ma[i].y1,ma[i].y2);
}
sort(ma+1,ma+n+1,cmp);
calc();
ma[0].x2=s;
int i=0,t=-1;
while(1)
{
t=-1;
for(int j=i+1;j<=n;j++)
if(under(i,j,ma[i].x2) && include(i,j) && (t==-1 || under(j,t,ma[i].x2)))//如果i可以到j,并且i的终点在j内,并且,j可以到t,更新
t=j;
if(t==-1) break;
i=t;
}
cout<<ma[i].x2<<endl;
return;
}
int main()
{
solve();
return 0;
}