1. 程式人生 > >POJ2826:An Easy Problem?!——題解(配特殊情況圖)

POJ2826:An Easy Problem?!——題解(配特殊情況圖)

while 一次 mes bsp print 情況下 queue blank using

http://poj.org/problem?id=2826

題目大意:給兩條線,讓它接豎直下的雨,問其能裝多少橫截面積的雨。

————————————————————————————

水題,看題目即可知道。

但是細節是真的多……不過好在兩次AC應該沒算被坑的很慘(全程沒查題解)。

推薦交之前看一下討論版的數據,方便一次AC(我第一次就是作死直接交了結果我自己都想好的情況忘了寫了……)

相信看到這篇題解的人都看過題了,那麽先說細節:

1.C++提交(G++不知道為什麽WA了……)

2.精度

3.特殊情況,看看下面哪種情況你沒有考慮到(以下都是沒法裝水的情況):

技術分享圖片技術分享圖片技術分享圖片技術分享圖片

技術分享圖片技術分享圖片

還有一種能夠接水的情況:

技術分享圖片

將上面考慮完了,應該就差不多了。

那麽說一下正解:

1.ko掉所有平行情況。(圖3)

2.ko掉所有不相交情況。(圖6)

3.ko掉所有斜率為0的情況。(圖5)

4.上述兩種情況完成後,求交點。

5.發現圖1和圖7情況只存在於斜率同號的情況下,特判之。

6.圖2和圖4一並解決:從交點處畫一條平行於x的線,如果在該線上方的點的個數不為2,則不能接水。

7.上述情況討論完後一定能接水,從6中獲得的兩個點取y值最小的點畫一條平行於x的線,則圍成的面積即為所求

總結:

線關系和線交點的題,細節較多,代碼實現較長較繁瑣,不推薦讀下面代碼。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<stack>
#include
<cmath> #include<algorithm> using namespace std; typedef double dl; const dl eps=1e-6; const dl INF=2147483647; struct point{ dl x; dl y; }p[5]; inline point getmag(point a,point b){ point s; s.x=b.x-a.x;s.y=b.y-a.y; return s; } inline dl multiX(point a,point b){ return a.x*b.y-b.x*a.y; } inline dl multiP(point a,point b){ return a.x*b.x+b.y*a.y; } inline bool parallel_mag(point a,point b){ if(fabs(a.x*b.y-a.y*b.x)<eps)return 1; return 0; } inline bool check(point a,point b,point c,point d){ if(multiX(getmag(c,d),getmag(c,a))*multiX(getmag(c,d),getmag(c,b))>eps)return 0; if(multiX(getmag(a,b),getmag(a,c))*multiX(getmag(a,b),getmag(a,d))>eps)return 0; return 1; } inline point intersection(point a,point b,point c,point d){ point s; dl a1=a.y-b.y,b1=b.x-a.x,c1=a.x*b.y-b.x*a.y; dl a2=c.y-d.y,b2=d.x-c.x,c2=c.x*d.y-d.x*c.y; s.x=(c1*b2-c2*b1)/(a2*b1-a1*b2); s.y=(a2*c1-a1*c2)/(a1*b2-a2*b1); return s; } inline dl slope(point a,point b){ if(fabs(a.x-b.x)<eps)return INF; return (a.y-b.y)/(a.x-b.x); } inline bool deng(point a,point b){ if(fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps)return 1; return 0; } inline bool pan(point s){ dl k1=slope(p[1],p[2]); dl k2=slope(p[3],p[4]); if(fabs(k1)<eps||fabs(k2)<eps)return 0; if(k1>eps&&k2>eps){ if(k2-k1>eps){ if(-eps<p[4].x-p[2].x)return 0; }else{ if(-eps<p[2].x-p[4].x)return 0; } } if(k1<-eps&&k2<-eps){ if(k1<k2){ if(p[3].x-p[1].x>-eps)return 0; }else{ if(p[1].x-p[3].x>-eps)return 0; } return 1; } int ok=0; for(int i=1;i<=4;i++){ if(p[i].y-s.y>eps){ ok++; } } if(ok!=2)return 0; return 1; } dl area(){ if(parallel_mag(getmag(p[1],p[2]),getmag(p[3],p[4])))return 0; if(!check(p[1],p[2],p[3],p[4]))return 0; point s=intersection(p[1],p[2],p[3],p[4]); if(!pan(s))return 0; int s1=0,s2=0; for(int i=1;i<=4;i++){ if(p[i].y-s.y>eps){ if(!s1)s1=i; else s2=i; } } point ns,nss,n1,n2; if(eps<p[s2].y-p[s1].y){ ns.x=p[s1].x;ns.y=p[s1].y; }else{ ns.x=p[s2].x;ns.y=p[s2].y; } nss.x=INF;nss.y=ns.y; n1=intersection(p[1],p[2],ns,nss); n2=intersection(p[3],p[4],ns,nss); return fabs(multiX(getmag(s,n1),getmag(s,n2)))/2; } int main(){ int t; scanf("%d",&t); while(t--){ for(int i=1;i<=4;i++)scanf("%lf%lf",&p[i].x,&p[i].y); if(p[1].x>p[2].x)swap(p[1],p[2]); if(p[3].x>p[4].x)swap(p[3],p[4]); printf("%.2f\n",area()); } return 0; }

POJ2826:An Easy Problem?!——題解(配特殊情況圖)