這個題最早的來源是小學奧數,六年級的時候,我們學到了格點的面積……求格點內的面積公式,又叫PICK公式。當然我只能呵呵了,完全不記得有這個公式……
由得,S=N+L/2-1,N屬于格子內的點,L屬於邊划過的格子。
INPUT給的是繪圖路徑而不是座標,所以說需要轉化成座標,求擦過邊的點,可以用GCD(點A,點B)來實現,可以用史上最古老的演算法——歐幾裡德演算法,LOG(N)的效率。
現在小學六年級就學這麼IMBA的東西,我真的無奈了!依稀記得當年會了個雞兔同籠高興的和個什麼似的。
#include <iostream> #include <cmath> #include <iomanip> using namespace std; class point { public: int x; int y; }; point inpath[300]; int gcd(int a,int b) { if(a==0) return b; if(b==0) return a; return gcd(b,a%b); } int pinside(point a,point b) { return gcd(abs(a.x-b.x),abs(a.y-b.y)); } double getarea(int n) { double result=0; for(int i=0;i<n;i++) { int a=inpath[(i+1)%n].x; int b=inpath[(i+1)%n].y; result+=((inpath[i].y*a)-(inpath[i].x*b))*1/2.0; } return fabs(result); } int main() { int testcase; cin>>testcase; for(int i=0;i<testcase;i++) { int n; cin>>n; int intmpx,intmpy,totalx=0,totaly=0; int onsideco=0,inmapco=0; double area=0; for(int k=0;k<n;k++) { cin>>intmpx>>intmpy; totalx+=intmpx; totaly+=intmpy; inpath[k].x=totalx; inpath[k].y=totaly; } for(int j=0;j<n;j++) { onsideco+= pinside(inpath[j],inpath[(j+1)%n]); } area=getarea(n); //由公式方便得到s=i+e/2-1,然後反向推算得裡面的點 inmapco=(area+1)-(onsideco/2.0); cout<<"Scenario #"<<i+1<<":"<<endl; cout<<inmapco<<" "<<onsideco; cout<<setiosflags(ios::fixed)<<setprecision(1)<<" "<<area<<endl; cout<<endl; } return 0; }