hdu3256計算幾何2

來源:互聯網
上載者:User

 http://acm.hdu.edu.cn/showproblem.php?pid=3256

2009 寧波網賽題。。此次網賽題難度相當不一般啊。。

 

題意:給定500條線段,以浮點型輸入最多4為小數。。。問這些線段覆蓋的整數點有多少個。。。。資料保證在-10000<x, y<10000。。。

 

分析:需要判重,所以不能直接做。。。總可能點數達到4*10^8個,所以不可能全部標記。。。因為線段條數不多,範圍也很小,可以直接枚舉x的座標標記y座標被覆蓋的個數。。。但如果標記每次都初始化為0的話複雜度4*10^8必然逾時,這裡有點小技巧就是flag標記值值初始化一次,然後更新為當前的x座標值即可。。這樣就是500*20000的複雜度了。。。

此題還比較變態啊。。。輸入的資料由於double精度問題不能直接輸入。。。所以只能變換輸入方式使得所有值都是精確地整數值。。。 

還有。。大於0和小於0時出現取餘是一定要注意分別判斷。。。wa了好久啊。。。

用double做死定過不了啊。。。鬱悶。。。

 

代碼:3000+ms

#include <string.h>#include <stdio.h>#include <algorithm>#include <cmath>#include <iostream>using namespace std;const int M=10010;const int N=510;char s[110];struct Line{__int64 x1, y1, x2, y2;} ll[N], pos;int n, flag[M*2], ans;void input(__int64 &a){scanf("%s", &s);int i, j, len=strlen(s);a = 0;i = 0;if(s[0]=='-')i++;for(; i<len && s[i]!='.'; i++){a *= 10;a += s[i]-'0';}for(i++, j=0; i<len; i++, j++){a *= 10;a += s[i]-'0';}while(j<4){a *= 10;j++;}if(s[0]=='-')a = -a;}void cal(int i, Line li){if(li.x1==li.x2){if(li.x1==i*10000){if(li.y1>li.y2)swap(li.y1, li.y2);if(li.y1<=0)         //小於0的情況沒考慮,這裡wa了好久啊。。。li.y1 = li.y1/10000; elseli.y1 = li.y1/10000+1;if(li.y2>=0) //...li.y2 /= 10000;elseli.y2 = li.y2/10000-1;for(int j=li.y1; j<=li.y2; j++){if(flag[j+M]!=i){flag[j+M] = i;ans++;}}}return;}if(!(li.x1<=i*10000 && i*10000<=li.x2) )return;if((i*10000-li.x1)*(li.y2-li.y1)%(li.x2-li.x1)==0){int j = (i*10000-li.x1)*(li.y2-li.y1)/(li.x2-li.x1)+li.y1;if(j%10000==0){j /= 10000;if(flag[j+M]!=i){flag[j+M] = i;ans++;}}}}int main(){int i, j, cas, cas1;scanf("%d", &cas);for(cas1=1; cas1<=cas; cas1++){scanf("%d", &n);pos.x1 = M*M*10;pos.x2 = -M*M*10;for(i=0; i<n; i++){input(ll[i].x1);input(ll[i].y1);input(ll[i].x2);input(ll[i].y2);if(ll[i].x1 > ll[i].x2){swap(ll[i].x1, ll[i].x2);swap(ll[i].y1, ll[i].y2);}if(ll[i].x1<pos.x1)pos.x1 = ll[i].x1;if(ll[i].x2<pos.x1)pos.x1 = ll[i].x2;if(ll[i].x1>pos.x2)pos.x2 = ll[i].x1;if(ll[i].x2>pos.x2)pos.x2 = ll[i].x2;}for(i=0; i<M*2; i++)flag[i] = -1000000;ans = 0;pos.x1 /= 10000;pos.x1--; //小於0的時候。。。wa啊。。。pos.x2 /= 10000;pos.x2++;for(i=pos.x1; i<=pos.x2; i++){for(j=0; j<n; j++){cal(i, ll[j]);}}printf("Case %d: %d\n", cas1, ans);}return 0;}

 代碼:double做的死wa。。

#include <string.h>#include <stdio.h>#include <algorithm>#include <cmath>#include <set>#include <iostream>using namespace std;const double eps=0.00005;int M=10001;const int N=510;struct Point {    double x, y;};struct Line{    Point a, b;} line[N];int n, ans, flag[20010];double xn, xx;inline double ffabs(double x){if(x<0)return -x;return x;}void cal(int i, Line li){double ii=i;    if(ffabs(li.a.x-li.b.x)<eps)    {        if(ffabs(li.a.x-ii)<eps)        {int yn, yx;            if(li.a.y>li.b.y)swap(li.a, li.b);if(li.a.y<=0)yn = li.a.y-eps;elseyn = li.a.y-eps+1;if(li.b.y>=0)yx = li.b.y+eps;elseyx = li.b.y+eps-1;            for(int j=yn; j<=yx; j++)            {                if(flag[j+M]!=i)                {                    ans++;                    flag[j+M] = i;                }            }        }        return;    }double y, y1;int yn;    if(li.a.x-ii>eps || ii-li.b.x>eps)        return;    y = (i-li.a.x)*(li.b.y-li.a.y)/(li.b.x-li.a.x)+li.a.y;    yn = y;    if(ffabs(y-yn)<0.00000001)    {        if(flag[yn+M]!=i)        {            flag[yn+M] = i;            ans++;        }    }}int main(){    int i, j, cas, cas1;    scanf("%d", &cas);    for(cas1=1; cas1<=cas; cas1++)    {        scanf("%d", &n);        xx = -10010;        xn = 10010;        for(i=0; i<n; i++)        {            scanf("%lf%lf%lf%lf", &line[i].a.x, &line[i].a.y, &line[i].b.x, &line[i].b.y);            if(line[i].a.x>line[i].b.x)                swap(line[i].a, line[i].b); //x從小到大。。。            if(line[i].b.x>xx)                xx = line[i].b.x;            if(line[i].a.x<xn)                xn = line[i].a.x;        }        ans = 0;        for(i=0; i<20010; i++)            flag[i] = -1000000;        for(i=xn-1; i<=xx+1; i++)        {            for(j=0; j<n; j++)                cal(i, line[j]);        }        printf("Case %d: %d\n", cas1, ans);    }    return 0;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.