ACM乐园
Love Me,Love My Code!
posts - 53,  comments - 24,  trackbacks - 0
http://acm.hdu.edu.cn/showproblem.php?pid=1542
//线段树+离散化计算覆盖矩形的面积并
//经典题目
#include <iostream>
#include 
<algorithm>
#include 
<map>
#include 
<iomanip>
#include 
<stdio.h>
using namespace std;

typedef pair
<double,int> mypair;//用于将double型的长度和int型的区间关联
double x[201],y[201],mx[201],my[201];//x,y存储原始数据,mx,my存储排序后的数据
map<double,int> m;
double lenth;//用于计算每回合覆盖的总长度

class tree //segment tree
{
public:
    
int begin,end,mid;
    
bool isoccupied;
    tree 
*left,*right; 
    tree()
{}
    tree(
int a,int b)//create tree
    {
        begin
=a;
        end
=b;
        mid
=(a+b)/2;
        
if(begin+1!=end)//若不是叶子节点,则递归建立线段树
        {
            left
=new tree(a,mid);
            right
=new tree(mid,b);
        }

    }


    
void clear()//clear tree
    {
        isoccupied
=false;
        
if(begin+1!=end)
        
{
            left
->clear();
            right
->clear();
        }

     }


    
void modify(int a,int b)//modify tree
    {
        
if(a>b)
            swap(a,b);
        
if(a==begin && b==end)//遇到正好标记的段,返回,不需要向下标记
        {
            isoccupied
=true;
            
return;
        }

        
if(begin+1==end)
        
return ;
        
if(b<=mid)
            left
->modify(a,b);
        
else if(a>=mid)
            right
->modify(a,b);
        
else
        
{
            left
->modify(a,mid);
            right
->modify(mid,b);
        }

    }


    
void sum()//compute sum
    {
        
if(isoccupied==true//只计算正好标记的段,防止重复计算
        {
            lenth
+=my[end]-my[begin];
            
return ;
        }

        
if(begin+1==end)
        
{
            
return;
        }

        
else
        
{
            left
->sum();
            right
->sum();
        }

    }

}
;

int main()
{
    
int i=1,n,j,k;
    
double result;
    
while(scanf("%d",&n),n)
    
{
        result
=0;//每次都要初始化
        m.clear();//清空树
        for(j=0;j<n;j++)
        
{
            scanf(
"%lf %lf %lf %lf",&x[2*j],&y[2*j],&x[2*j+1],&y[2*j+1]);
        }

        
for(j=0;j<2*n;j++)
        
{
            mx[j]
=x[j];
            my[j]
=y[j];
        }

        sort(mx,mx
+2*n);
        sort(my,my
+2*n);
        
for(j=0;j<2*n;j++)//将y坐标与区间关联,查找方便
            m.insert(mypair(my[j],j));
        tree 
*root=new tree(0,2*n-1);//建立线段树,注意从0开始,因为my数组是从0开始的,要保持照应
        for(j=0;j<2*n-1;j++//注意是2*n-1,不是2*n
        {
            
double temp=mx[j+1]-mx[j];//横向分割段长
            lenth=0;                  //纵向段长清零
            root->clear();            //每次都要重新计算纵向段长
            for(k=0;k<n;k++)
            
{
                
if(x[2*k]<=mx[j] && x[2*k+1]>=mx[j+1])//当某矩形纵向包含当前分割段时,说明它包含要计算的块
                    root->modify(m[y[2*k]],m[y[2*k+1]]);//调整y[2*k],y[2*k+1]对应的段
            }

            root
->sum();
            result
+=temp*lenth;
        }

        printf(
"Test case #%d\nTotal explored area: %.2f\n\n",i++,result);
    }

}



posted on 2011-05-27 23:45 大大木马 阅读(628) 评论(0)  编辑 收藏 引用

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



<2011年5月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(1)

随笔档案(53)

文章档案(2)

搜索

  •  

积分与排名

  • 积分 - 62483
  • 排名 - 353

最新评论

阅读排行榜

评论排行榜