P1766 液体滴落
题目传送门
这是一道数学和贪心结合的题目。
我们先讨论贪心使用,本题贪心的作用只是一个优化。每次滴落时选取最高的线段(即\(y\)最大),因为这样能保证水滴按题意流动。
本题关键是数学,也很简单,已知两点求线段解析式。最后进行一个小小的模拟即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=10000+10,INF=INT_MAX;
int m,n,y=INF;
struct xiemian{
int sx,sy,fx,fy;
double k,b;
bool flag;
}a[N];
int main(){
cin>>m>>n;
for(int i=1;i<=m;i++){
cin>>a[i].sx>>a[i].sy>>a[i].fx>>a[i].fy;
if(a[i].sx>a[i].fx){
swap(a[i].sx,a[i].fx);
swap(a[i].sy,a[i].fy);
}
a[i].k=(a[i].sy-a[i].fy)*1.0/(a[i].sx-a[i].fx);
a[i].b=a[i].sy-a[i].k*a[i].sx;
}
while(1){
ll xm=0,zuigao=-INF;
for(int i=1;i<=m;i++){
if(!a[i].flag&&a[i].sx<=n&&n<=a[i].fx&&a[i].k*n+a[i].b<=y)
if(a[i].k*n+a[i].b>zuigao){
zuigao=a[i].k*n+a[i].b;
xm=i;
}
}
if(xm==0)break;
if(a[xm].k>0)n=a[xm].sx,y=min(a[xm].fy,a[xm].sy);
else n=a[xm].fx,y=min(a[xm].fy,a[xm].sy);
a[xm].flag=1;
}
cout<<n<<endl;
return 0;
}