map.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:11k
开发平台:

MultiPlatform

  1. #include <LEDA/basic.h>
  2. #include <LEDA/slist.h>
  3. #include <LEDA/plane.h>
  4. #include <LEDA/window.h>
  5.  
  6. #include<math.h>
  7.  
  8. const int WORDS = 6;    // maximal size of placement vectors (in words)
  9. const int N     = 96;   // maximal number of input points = 16 * WORDS
  10. typedef unsigned long word;
  11. class PLACEMENT
  12. {
  13.   word A[WORDS];
  14.   word cache;      // cache of 16 last written entries
  15.  
  16.   public:
  17.   PLACEMENT();
  18.   PLACEMENT(const PLACEMENT&);
  19.   word get_last_word() const { return cache;}
  20.   word get_last_word(int i) const 
  21.   { return (i>0) ? (cache << ((16-i)<<1)) : 0; }
  22.   
  23.   int read(int i) const 
  24.   { return (A[i>>4] >> ((i&15)<<1)) & 3; }
  25.  
  26.   void write(int i, int pos) 
  27.   { A[i>>4] |= (pos << ((i&15)<<1));
  28.     cache <<=2;
  29.     cache |= pos;
  30.    } 
  31.  
  32.   LEDA_MEMORY(PLACEMENT)
  33.  
  34. };
  35. PLACEMENT::PLACEMENT()
  36. { for(int i = 0; i < WORDS; i++) A[i] = 0; }
  37. PLACEMENT::PLACEMENT(const PLACEMENT& P)
  38. { cache = P.cache;
  39.   for(int i = 0; i < WORDS; i++) A[i] = P.A[i]; 
  40. }
  41.  
  42.  
  43. typedef PLACEMENT* placement;
  44.  
  45. static window W(600,650);
  46.  
  47. static color node_color1 = blue;
  48. static color node_color2 = red;
  49. static color node_color3 = green;
  50. static color rect_color  = yellow;
  51.  
  52. void draw_rec(window& W, double x1, double y1, double x2, double y2)
  53. { if (!W.mono())
  54.       W.draw_filled_rectangle(x1,y1,x2,y2,rect_color);
  55.   W.draw_rectangle(x1,y1,x2,y2);
  56.  }
  57.  
  58.  
  59. void draw_config(window& W, const list<point>& L, PLACEMENT& P, double sig, 
  60.                                                                 int maxp = -1)
  61. {
  62.         /*--------*--------*
  63.          |        |        |
  64.          |   0    |    1   |
  65.          |        |        |
  66.          *--------p--------*
  67.          |        |        |
  68.          |   2    |    3   |
  69.          |        |        |
  70.          *--------*--------*/
  71.  
  72.   int   i=0;
  73.   point p;
  74.  
  75.   if (maxp <0) maxp = L.length();
  76.  
  77.   W.clear();
  78.  
  79.   forall(p,L)
  80.   {
  81.     double x = p.xcoord();
  82.     double y = p.ycoord();
  83.  
  84.     int  pos = P.read(i++);
  85.  
  86.     switch(pos)
  87.     { case 0 : draw_rec(W,x,y,x-sig,y+sig);
  88.                break;
  89.  
  90.       case 1 : draw_rec(W,x,y,x+sig,y+sig);
  91.                break;
  92.       
  93.       case 2 : draw_rec(W,x,y,x-sig,y-sig);
  94.                break; 
  95.       
  96.       case 3 : draw_rec(W,x,y,x+sig,y-sig);
  97.                break;
  98.     }
  99.     if (i > maxp) break;
  100.   }
  101.  
  102.   forall(p,L) W.draw_filled_node(p,node_color1);
  103.  
  104. }
  105.  
  106.  
  107.  
  108.  
  109. int** D[N][4];   // D[N][4][N][4]
  110.                  //  
  111.                  // D[p][i][q][j] gives maximal possible sigma for square at 
  112.                  // point p in position i and square at point q in position j
  113.  
  114.  
  115. void initialize_matrix(const list<point>& p_list)
  116. {
  117.   list_item it1, it2;
  118.  
  119.   int n = p_list.length();
  120.  
  121.   int i,j,p1,p2;
  122.  
  123.   for(i=0;i < n; i++)
  124.      for(p1=0;p1 < 4; p1++)
  125.      { int** ptr = new int*[n];
  126.        D[i][p1] = ptr;
  127.        for(j=0; j<n; j++) ptr[j] = new int[4];
  128.        }
  129.  
  130.  
  131.   i = 0;
  132.   forall_items(it1,p_list)
  133.   { 
  134.     point p = p_list[it1];
  135.  
  136.     j = 0;
  137.     forall_items(it2,p_list)
  138.      { 
  139.        if (it1==it2) break;
  140.  
  141.        point q = p_list[it2];
  142.  
  143.  
  144.        int xrel  = int(p.xcoord() - q.xcoord());
  145.        int yrel  = int(p.ycoord() - q.ycoord());
  146.        int xdist = int(fabs(xrel));
  147.        int ydist = int(fabs(yrel));
  148.        int max_xy = Max(xdist,ydist);
  149.  
  150.        int d_00  = max_xy;
  151.        int d_01  = (xrel>0) ? Max(xdist/2,ydist) : MAXINT;
  152.        int d_01r = (xrel<0) ? Max(xdist/2,ydist) : MAXINT;
  153.        int d_02  = (yrel<0) ? Max(xdist,ydist/2) : MAXINT;
  154.        int d_02r = (yrel>0) ? Max(xdist,ydist/2) : MAXINT;
  155.        int d_03  = (xrel>0 && yrel<0) ? max_xy/2 : MAXINT;
  156.        int d_03r = (xrel<0 && yrel>0) ? max_xy/2 : MAXINT;
  157.        int d_12  = (xrel<0 && yrel<0) ? max_xy/2 : MAXINT;
  158.        int d_12r = (xrel>0 && yrel>0) ? max_xy/2 : MAXINT;
  159.  
  160.  
  161.        for(p1=0; p1<4;p1++)
  162.          for(p2=0; p2<4;p2++)
  163.           switch(p1 - p2)
  164.           {
  165.             case  0 : D[i][p1][j][p2] = d_00;
  166.                       break;
  167.      
  168.             case -1 : D[i][p1][j][p2] = (p1==1) ? d_12 : d_01;
  169.                       break;
  170.      
  171.             case  1 : D[i][p1][j][p2] = (p1==2) ? d_12r : d_01r;
  172.                       break;
  173.      
  174.             case -2 : D[i][p1][j][p2] = d_02;
  175.                       break;
  176.      
  177.             case  2 : D[i][p1][j][p2] = d_02r;
  178.                       break;
  179.      
  180.             case -3 : D[i][p1][j][p2] = d_03;
  181.                       break;
  182.      
  183.             case  3 : D[i][p1][j][p2] = d_03r;
  184.                       break;
  185.           }
  186.     
  187.       j++;
  188.      }
  189.  
  190.     i++;
  191.  
  192.    }
  193.  
  194. }
  195.  
  196.  
  197.  
  198. bool find_placement(list<point>& L, int sigma, PLACEMENT& P)
  199.   // determines whether a placement is possible and returns it in P 
  200.   // P is unchanged if there is no placment possible 
  201.   
  202.   slist<placement> T,Tnew;
  203.  
  204.   int n = L.length();
  205.  
  206.   placement v;
  207.  
  208.   register int   p,q,k,i;
  209.   register word  buf,plw;
  210.   register int** dist_to_p;
  211.  
  212.   point a;
  213.  
  214.   float X[N];
  215.   float Y[N];
  216.  
  217.   p = 0;
  218.  
  219.   forall(a,L) 
  220.   { X[p] = a.xcoord();
  221.     Y[p] = a.ycoord();
  222.     p++;
  223.    }
  224.  
  225.   placement Pnew = new PLACEMENT;
  226.  // we perform a sweep the strip consists of points q .. p-1 
  227.  
  228.  
  229.  // initialization for the sweep; the strip is empty; the first point to 
  230.  // enter is point 0; T consists of a single placement which is undefined 
  231.  // for all points 
  232.  
  233.  
  234.  p = 0; // next point to enter the strip
  235.  q = 0; // next point to leave the strip
  236.  
  237.  T.append(Pnew);        
  238.  
  239.  // The sweep: 
  240.  // we proceed as long as there is still a point to be processed and 
  241.  // the set T of legal placements is not empty 
  242.  while (p < L.length() && !T.empty())
  243.  { 
  244.    // we decide whether p enters the strip or q leaves the strip 
  245.  
  246.    if (p == 0 || X[p]-X[q] < 2*sigma)
  247.      { 
  248.        // p enters the strip
  249.        // we combine the four possible placements of p 
  250.        // with all placements in T
  251.        if (p-q > 16) error_handler(1,"too many points in strip");
  252.        W.draw_filled_node(X[p],Y[p],node_color3);
  253.        for(i=0; i<4; i++)
  254.        { 
  255.          dist_to_p = D[p][i];
  256.  
  257.          forall(v,T)
  258.          { // check whether v[q...p-1] can be extended by placement i for p 
  259.  
  260.            for(k = p-1, buf = v->get_last_word(); k >= q; k--, buf >>= 2)
  261.              if (dist_to_p[k][buf&3] < sigma) break;
  262.  
  263.            if (k < q)                
  264.            { // position i for p is compatible with placement vector v
  265.              Pnew = new PLACEMENT(*v);
  266.              Pnew->write(p,i);
  267.              Tnew.append(Pnew); 
  268.   
  269.              if (W.get_button() != 0) 
  270.              { color save = rect_color;
  271.                if (!W.mono()) rect_color = violet;
  272.                draw_config(W,L,*Pnew,sigma,p);
  273.                rect_color = save;
  274.                for(int i=q; i<=p; i++)
  275.                   W.draw_filled_node(X[i],Y[i],node_color2);
  276.                W.draw_filled_node(X[p],Y[p],node_color3);
  277.                W.read_mouse();
  278.                W.clear();
  279.                for(i=0; i<q; i++)
  280.                   W.draw_filled_node(X[i],Y[i],node_color1);
  281.                for(i=q; i<=p; i++)
  282.                   W.draw_filled_node(X[i],Y[i],node_color2);
  283.                for(i=p+1; i<n; i++)
  284.                   W.draw_filled_node(X[i],Y[i],node_color1);
  285.               }
  286.   
  287.             }
  288.  
  289.           }
  290.         }
  291.        W.draw_filled_node(X[p],Y[p],node_color2);
  292.  
  293.        p++;
  294.  
  295.        forall(v,T) delete v;
  296.  
  297.       } 
  298.     else 
  299.      { // q leaves the strip
  300.        W.draw_filled_node(X[q],Y[q],node_color1);
  301.        q++;
  302.  
  303.        // remove placement vectors identical in [q+1 ... p] from T
  304.  
  305.        plw = T.head()->get_last_word(p-q);
  306.  
  307.        Tnew.append(T.pop());
  308.  
  309.        forall(v,T)
  310.        { buf = v->get_last_word(p-q);
  311.          if (buf == plw)
  312.            delete v;
  313.          else 
  314.            { plw = buf;
  315.              Tnew.append(v);
  316.             }
  317.         }
  318.       }
  319.  
  320.     T.clear();
  321.     T.conc(Tnew); // clears Tnew
  322.     W.draw_text(-80,-60,string("k = %2d   |T| = %5d   ",p-q+1,T.length()));
  323.  
  324.  } // end of sweep 
  325.  while (q < p)
  326.  { W.draw_filled_node(X[q],Y[q],node_color1);
  327.    q++;
  328.   }
  329.  
  330.  if (T.empty()) 
  331.      return false;
  332.  else 
  333.     { P = *(T.head());
  334.       forall(v,T) delete v;
  335.       return true;
  336.      }
  337.  
  338. } // end of find_placement 
  339.  
  340.  
  341.  
  342. main()
  343.   // In the first implementation we deal only with points 
  344.   // whose coordinates are integers in the range 1 .. 999;
  345.   // the algorithms consists of two steps: 
  346.   // In the first step we generate the problem and in the second step we 
  347.   // determine the optimal sigma by binary search 
  348.   // generation of the problem; we ask the user for the number of points
  349.   // then generate the appropriate number of random points 
  350.  
  351.  
  352.   W.init(-100,1100,-100);
  353.   W.set_node_width(5);
  354.   W.set_text_mode(opaque);
  355.  
  356.   if (W.mono()) 
  357.   { node_color1 = white;
  358.     node_color2 = black;
  359.    }
  360.  
  361.   int n = 50;
  362.   int input = 0;
  363.   int grid_width = 0;
  364.  
  365.   list<point> L;
  366.  
  367.   panel P;
  368.  
  369.   P.text_item("                                      ");
  370.   P.text_item("        A Plane Sweep Algorithm       ");
  371.   P.text_item("                 for a                ");
  372.   P.text_item("       Geometric Packing Problem      ");
  373.   P.text_item("                                      ");
  374.   P.text_item("                  ...                 ");
  375.   P.text_item("                  ...                 ");
  376.   P.text_item("                                      ");
  377.   P.int_item("points", n,1,80);
  378.   P.int_item("grid", grid_width, 0,40,10);
  379.  
  380.   P.button("random");
  381.   P.button("mouse");
  382.   P.button("quit");
  383.  
  384.  
  385.   for(;;)
  386.   {
  387.     int but = P.open(0,0);
  388.  
  389.     W.clear();
  390.     W.set_grid_mode(grid_width);
  391.     L.clear();
  392.  
  393.     switch(but)  {
  394.  
  395.     case 0: { for(int i=0; i<n; i++) 
  396.               { double x =  rand_int(1,999);
  397.                 double y =  rand_int(1,999);
  398.                 L.append(point(x,y));
  399.                 W.draw_filled_node(x,y,node_color1);
  400.                }
  401.                break;
  402.              }
  403.  
  404.      case 1: { point p;
  405.                while (W >> p) 
  406.                { L.append(p);
  407.                  W.draw_filled_node(p,node_color1);
  408.                 }
  409.                break;
  410.               }
  411.  
  412.  
  413.      case 2: { exit(0);
  414.                break;
  415.               }
  416.              
  417.     }
  418.  
  419.     n = L.length();
  420.  
  421.     W.set_frame_label(string("%d points",n));
  422.  
  423.  
  424.  
  425.      // sort points  and initialize distance matrix
  426.    
  427.      L.sort();
  428.  
  429.      initialize_matrix(L);
  430.    
  431.      PLACEMENT PL;
  432.  
  433.      int low  =   1;
  434.      int high = 999;
  435.  
  436.      find_placement(L,low,PL);
  437.  
  438.      // binary search
  439.    
  440.      while (high > low+1)
  441.      { 
  442.        // Invariant:  a) PL is placement for "sigma = low"
  443.        //             b) no placement possible for "sigma = high"
  444.    
  445.        int mid = (high + low)/2;
  446.    
  447.        W.del_message();
  448.        W.message(string("%3d <= sigma < %3d      %3d ??",low, high, mid));
  449.    
  450.        if (find_placement(L,mid,PL))
  451.           { draw_config(W,L,PL,mid);
  452.             low = mid;
  453.            }
  454.         else 
  455.             high = mid;
  456.       }
  457.    
  458.      // end of the binary search 
  459.      // low is the optimal side length, PL the corresponding placement 
  460.    
  461.      W.del_messages();
  462.      W.message(string("sigma = %d",low));
  463.    }
  464.                 
  465.   return 0;
  466. }