随笔-14  评论-21  文章-0  trackbacks-0

可以用以下方法构造出一组解,从第n个菱形开始依次放置,放置第i个菱形时必须覆盖p1,p2,...,pi这些点且被第i+1个菱形包含
此时菱形中点的可行区域其实是一个特殊的半平面交(只有4种方向的半平面),呵呵~
我用了4个堆去维护这四个半平面,时间复杂度为O(nlogn)
找可行区域的整点时要注意一下,不能出现0.5什么的

#include <iostream>
#include 
<cstdlib>
#include 
<cstdio>

using namespace std;

int n,x[210],y[210],d[210],rx[210],ry[210];

struct heap
{
  
int t1,t2;
  
bool cmp(const int &u,const int &v)
  { 
return t1*x[u]+t2*y[u]>t1*x[v]+t2*y[v]; }
  
int n,h[210],e[210];
  
void del(int i)
  {
    e[h[i]]
=0;
    
if (i==n)
    { n
--return; }
    h[i]
=h[n--]; e[h[i]]=i;
    down(i); up(i);
  }
  
void build(void)
  {
    
for(int i=(n>>1);i>=1;i--)
      down(i);
  }
  
void up(int i)
  {
    
int t,j;
    
while(i>1)
    {
      j
=(i>>1);
      
if (cmp(h[i],h[j]))
      { 
        t
=h[i]; h[i]=h[j]; h[j]=t;
        e[h[i]]
=i; e[h[j]]=j;
      }
      
else break;
      i
=j;
    }
  }
  
void down(int i)
  {
    
int t,j;
    
while((j=(i<<1))<=n)
    {
      
if (j<n&&cmp(h[j+1],h[j])) j++;
      
if (cmp(h[j],h[i]))
      { 
        t
=h[i]; h[i]=h[j]; h[j]=t;
        e[h[i]]
=i; e[h[j]]=j;
      }
      
else break;
      i
=j;
    }
  }
}h1,h2,h3,h4;

int main(void)
{
  
int u,c,i,l1,r1,l2,r2;
  scanf(
"%d",&c);
  
for(u=1;u<=c;u++)
  {
    scanf(
"%d",&n);
    h1.n
=h2.n=h3.n=h4.n=n;
    
for(i=1;i<=n;i++)
    {
      scanf(
"%d%d%d",x+i,y+i,d+i);
      h1.h[i]
=h1.e[i]=i;
      h2.h[i]
=h2.e[i]=i;
      h3.h[i]
=h3.e[i]=i;
      h4.h[i]
=h4.e[i]=i;
    }
    h1.t1
=1; h1.t2=1;
    h2.t1
=-1; h2.t2=1;
    h3.t1
=-1; h3.t2=-1;
    h4.t1
=1; h4.t2=-1;
    h1.build();
    h2.build();
    h3.build();
    h4.build();
    
for(i=n;i>=1;i--)
    {
      l1
=x[h1.h[1]]+y[h1.h[1]]-d[i];
      r1
=x[h3.h[1]]+y[h3.h[1]]+d[i];
      l2
=-x[h2.h[1]]+y[h2.h[1]]-d[i];
      r2
=-x[h4.h[1]]+y[h4.h[1]]+d[i];
      
if (i<n)
      {
        r1
=min(r1,rx[i+1]+ry[i+1]+d[i+1]-d[i]);
        l1
=max(l1,rx[i+1]+ry[i+1]-d[i+1]+d[i]);
        r2
=min(r2,-rx[i+1]+ry[i+1]+d[i+1]-d[i]);
        l2
=max(l2,-rx[i+1]+ry[i+1]-d[i+1]+d[i]);
      }
      
if ((l1+l2)%2!=0)
        
if (l1<r1)
          l1
++;
        
else l2++;
      rx[i]
=(l1-l2)/2;
      ry[i]
=(l1+l2)/2;
      h1.del(h1.e[i]);
      h2.del(h2.e[i]);
      h3.del(h3.e[i]);
      h4.del(h4.e[i]);
    }
    printf(
"Case %d:\n",u);
    
for(i=1;i<=n;i++)
      printf(
"%d %d\n",rx[i],ry[i]);
  }
  
return 0;
}
posted on 2010-10-01 16:48 zxb 阅读(142) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理