Advertisement
bartekltg

NOZ

Nov 27th, 2012
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.66 KB | None | 0 0
  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <set>
  6.  
  7. using namespace std;
  8.  
  9. class punkt
  10. {public:
  11.     int indeks;
  12.     int x,y;
  13.     int sasiad_pionowy, sasiad_poziomy;
  14.     signed char kierunek_x, kierunek_y;
  15.     bool odwiedzony;
  16.     bool wewnetrzny; // czy wiercholek skierowany jest do wewnatrz.
  17.     punkt(){};
  18.     punkt(int _x, int _y, int i){ indeks=i; x=_x; y=_y; sasiad_pionowy=-1; sasiad_poziomy=-1; odwiedzony=false; }
  19. };
  20. typedef punkt* ppunkt ;
  21.  
  22. struct sortuj_x_y
  23.  {
  24.      bool operator () (const punkt* a, const punkt* b)const
  25.      {   return ((a->x < b->x) || ( (a->x == b->x)&&(a->y < b->y)   ) ) ;    }
  26. }sortxy;
  27.  
  28. struct sortuj_x
  29.  {
  30.      bool operator () (const punkt* a, const punkt* b)const
  31.      {   return (a->x < b->x) ;  }
  32. };
  33.  
  34. struct sortuj_y
  35.  {
  36.      bool operator () (const punkt* a, const punkt* b)const
  37.      {   return (a->y < b->y) ;  }
  38. };
  39.  
  40. struct sortuj_y_x
  41.  {
  42.      bool operator () ( punkt *a,  punkt *b)const
  43.      {   return ((a->y < b->y) || ( (a->y == b->y)&&(a->x < b->x)   ) ) ;    }
  44. }sortyx;
  45.  
  46.  
  47. inline signed char norm_kier(int k)//normalizuj liczbę do jej znaku
  48. {
  49.     if (k==0)return 0;
  50.     else
  51.     return (k>=0)?1:-1;
  52. }
  53.  
  54. int iloczyn ( vector <punkt > & punkty, int i  )
  55. {
  56.     int n=punkty.size();
  57.     int X2 = norm_kier( punkty[(i+1)%n].x - punkty[i].x );
  58.     int Y2 = norm_kier( punkty[(i+1)%n].y - punkty[i].y );
  59.     int X1 = norm_kier( punkty[i].x - punkty[(n+i-1)%n].x );
  60.     int Y1 = norm_kier( punkty[i].y - punkty[(n+i-1)%n].y );
  61.     return (X2*Y1)-(X1*Y2);
  62. }
  63.  
  64. int main()
  65. {
  66.  
  67.     int n;
  68.     scanf("%d",&n);
  69.  
  70.     vector <punkt > punkty(n);
  71.     for (int i=0;i<n;i++)
  72.     {
  73.         int x,y;
  74.         scanf("%d %d",&x,&y);
  75.         punkty[i]=punkt(x,y,i);
  76.     }
  77.     for (int i=0;i<n;i++)
  78.     {
  79.         punkty[i].kierunek_x= norm_kier(punkty[(i+1)%n].x+punkty[(n+i-1)%n].x - 2*punkty[i].x);
  80.         punkty[i].kierunek_y= norm_kier(punkty[(i+1)%n].y+punkty[(n+i-1)%n].y - 2*punkty[i].y);
  81.     }
  82.  
  83.     vector<punkt*> pun(n);
  84.  
  85.     for (int i=0;i<n;i++)
  86.     {
  87.         pun[i]=(&punkty[i]);
  88.     }
  89.  
  90.    
  91.     std::sort(pun.begin(),pun.end(),sortyx);//najpierw po x, potem po y
  92.  
  93.     int it = pun[0]->indeks; //ekstremalny wierzcholek nie moze byc wewnatrznym
  94.     int zewnetrzny = iloczyn( punkty,it );
  95.     for (int i=0;i<n;i++)
  96.     {
  97.         punkty[i].wewnetrzny=( iloczyn(punkty,i)!=zewnetrzny );
  98.     }
  99.  
  100.  
  101.     {
  102.         set <punkt*,sortuj_x> wolne;
  103.         set <punkt*,sortuj_x>::iterator A,B;
  104.  
  105.    
  106.         int k=0;
  107.         do
  108.         {
  109.             int miotla_y=pun[k]->y;
  110.  
  111.             while ((k<n)&&(pun[k]->y==miotla_y))
  112.             {
  113.                 punkt *a,*b;
  114.                 a = pun[k];
  115.                 b = pun[k+1];
  116.                 k+=2;
  117.  
  118.                 A = wolne.lower_bound(a);
  119.                 B = wolne.upper_bound(b);
  120.  
  121.                 //if (A==wolne.end())printf("end");
  122.  
  123.                 if ( (A!=wolne.end()) && (A!=B))//coś znalezlismy
  124.                 {
  125.                     if( (a->x == (*A)->x) &&abs(a->indeks - (*A)->indeks)!=1 )
  126.                     {
  127.                         a->sasiad_pionowy = (*A)->indeks;
  128.                         (*A)->sasiad_pionowy = a->indeks;
  129.                     }
  130.                 //  if (A==wolne.end())printf("NIE");
  131.                     B--; //tam mozę być kandydat; Poprzednik zawsze istnieje bo A=\=B
  132.                     if(( b->x == (*B)->x )  &&abs(b->indeks - (*B)->indeks)!=1 )
  133.                     {
  134.                         b->sasiad_pionowy = (*B)->indeks;
  135.                         (*B)->sasiad_pionowy = b->indeks;
  136.                     }
  137.                     B++;
  138.                 }
  139.                 wolne.erase(A,B);
  140.                 if ((a->kierunek_y<0)&&(a->wewnetrzny))
  141.                 {
  142.                     wolne.insert(a);
  143.                 }
  144.                 if ((b->kierunek_y<0)&&(b->wewnetrzny))
  145.                 {
  146.                     wolne.insert(b);
  147.                 }
  148.             }//while (pun[k]->y==miotla_y)
  149.         }while (k<n);
  150.  
  151.     }
  152.     //////////////////////copypasta
  153.         std::sort(pun.begin(),pun.end(),sortxy);//najpierw po y, potem po x
  154.    
  155.     {
  156.         set <punkt*,sortuj_y> wolne;
  157.         set <punkt*,sortuj_y>::iterator A,B;
  158.  
  159.    
  160.         int k=0;
  161.         do
  162.         {
  163.             int miotla_x=pun[k]->x;
  164.  
  165.             while ((k<n)&&(pun[k]->x==miotla_x))
  166.             {
  167.                 punkt *a,*b;
  168.                 a = pun[k];
  169.                 b = pun[k+1];
  170.                 k+=2;
  171.  
  172.                 A = wolne.lower_bound(a);
  173.                 B = wolne.upper_bound(b);
  174.  
  175.                 //if (A==wolne.end())printf("end");
  176.  
  177.                 if ( (A!=wolne.end()) && (A!=B))//coś znalezlismy
  178.                 {
  179.                     if( (a->y == (*A)->y) &&abs(a->indeks - (*A)->indeks)!=1 )
  180.                     {
  181.                         a->sasiad_poziomy = (*A)->indeks;
  182.                         (*A)->sasiad_poziomy = a->indeks;
  183.                     }
  184.                     //if (A==wolne.end())printf("NIE");
  185.                     B--; //tam mozę być kandydat; Poprzednik zawsze istnieje bo A=\=B
  186.                     if(( b->y == (*B)->y )  &&abs(b->indeks - (*B)->indeks)!=1 )
  187.                     {
  188.                         b->sasiad_poziomy = (*B)->indeks;
  189.                         (*B)->sasiad_poziomy = b->indeks;
  190.                     }
  191.                     B++;
  192.                 }
  193.                 wolne.erase(A,B);
  194.                 if ((a->kierunek_x<0)&&(a->wewnetrzny))
  195.                 {
  196.                     wolne.insert(a);
  197.                 }
  198.                 if ((b->kierunek_x<0)&&(b->wewnetrzny))
  199.                 {
  200.                     wolne.insert(b);
  201.                 }
  202.             }//while (pun[k]->y==miotla_y)
  203.         }while (k<n);
  204.  
  205.     }
  206.  
  207.     ////////////////////////copypasta
  208.    
  209.     int wynik = (n-4)/2;
  210.     //printf("/n/n");
  211.     for (int i=0; i<n;i++)
  212.     {
  213.         int licznik=0;
  214.         if (!punkty[i].odwiedzony)
  215.         {
  216.             int j=i;
  217.             //printf("%d %d\n",punkty[j].x,punkty[j].y);
  218.             while (1)
  219.             {
  220.                 if (punkty[j].sasiad_pionowy==-1) break;
  221.                 j = punkty[j].sasiad_pionowy;
  222.                 if (punkty[j].odwiedzony) break;
  223.                 licznik++;
  224.                
  225.                 punkty[j].odwiedzony=true;
  226.                
  227.                 if (punkty[j].sasiad_poziomy==-1) break;
  228.                 j = punkty[j].sasiad_poziomy;
  229.                 if (punkty[j].odwiedzony) break;
  230.                 licznik++;
  231.                 punkty[j].odwiedzony=true;
  232.             }
  233.             j=i;
  234.             punkty[j].odwiedzony=true;
  235.  
  236.            
  237.             while (1)
  238.             {
  239.                 if (punkty[j].sasiad_poziomy==-1) break;
  240.                 j = punkty[j].sasiad_poziomy;
  241.                 if (punkty[j].odwiedzony) break;
  242.                 licznik++;
  243.                 punkty[j].odwiedzony=true;
  244.  
  245.                 if (punkty[j].sasiad_pionowy==-1) break;
  246.                 j = punkty[j].sasiad_pionowy;
  247.                 if (punkty[j].odwiedzony) break;
  248.                 licznik++;
  249.                 punkty[j].odwiedzony=true;
  250.             }
  251.             //printf("%d %d\n",i,licznik);
  252.             wynik -= (licznik+1)/2;
  253.         }//if (punkty[i].odwiedzony)
  254.     }
  255.    
  256.     printf("%d\n",wynik);
  257.    
  258.     return 0;
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement