poj 1151 Atlantis 二分查找+离散化

265 篇文章 1 订阅
15 篇文章 0 订阅

Atlantis
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 17464 Accepted: 6654

Description

There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

Input

The input consists of several test cases. Each test case starts with a line containing a single integer n (1 <= n <= 100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area. 
The input file is terminated by a line containing a single 0. Don't process it.

Output

For each test case, your program should output one section. The first line of each section must be "Test case #k", where k is the number of the test case (starting with 1). The second one must be "Total explored area: a", where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point. 
Output a blank line after each test case.

Sample Input

2
10 10 20 20
15 15 25 25.5
0

Sample Output

Test case #1
Total explored area: 180.00 


I met several bugs:

1. printf("%.2f", res);  for double type instead of the setence printf("%.2lf", res);   because for g++, %lf is not supported, so we must use %f for output and %lf for input. 

2. Output a blank line after each test case.


#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <limits.h>
#include <assert.h>
#include <stdio.h>
using namespace std;


class Rec {
 public:
  double ltx, lty, rdx, rdy;
  Rec(double x1 = 0, double y1 = 0, double x2 = 0, double y2 = 0): ltx(x1), lty(y1), rdx(x2), rdy(y2){
  }
};
class Inte {
public:
  double s, e;  
  Inte(double s1 = 0, double e1 = 0) : s(s1), e(e1) {
  }
};
class cmp1 {
 public:
  bool operator()(const Inte& inte1, const Inte& inte2) const{
    return inte1.s == inte2.s ? inte1.e < inte2.e : inte1.s < inte2.s;
  }
};

class Solution{
 public:

  vector<Inte> merge(vector<Inte>& inte) {
    vector<Inte> res;
    if (inte.empty())
      return res;
    sort(inte.begin(), inte.end(), cmp1());

    Inte cur(inte[0].s, inte[0].e);
    int size = inte.size();
    for (int i = 1; i < size; ++i) {
      if (inte[i].s > cur.e) {
        res.push_back(cur);
        cur.s = inte[i].s, cur.e = inte[i].e;
      }
      else {
        cur.s = min(cur.s, inte[i].s);
        cur.e = max(cur.e, inte[i].e);
      }
    }
    res.push_back(cur);
    return res;
    
  }

  double calArea(vector<vector<Inte> >& inters, const vector<double>& xcoor) {
    double res = 0;
    int size = inters.size();
    for (int i = 0; i < size; ++i) {
      vector<Inte> cur = merge(inters[i]);

      int cursize = cur.size();
      for (int j = 0; j < cursize; ++j)
        res += (cur[j].e - cur[j].s)*(xcoor[i+1]-xcoor[i]);
    }
    return res;
  }
  double calAllArea(const vector<Rec>& recs) {
    int i, size = recs.size(), j, intesize;
    vector<double> xcoor;
    
    for (i = 0; i < size; ++i) {
      xcoor.push_back(recs[i].ltx);
      xcoor.push_back(recs[i].rdx);
    }
    sort(xcoor.begin(), xcoor.end());
    xcoor.resize(unique(xcoor.begin(), xcoor.end()) - xcoor.begin());
    intesize = xcoor.size() - 1;
    vector<vector<Inte> > inters(intesize, vector<Inte>(0));
    
    
    for (i = 0; i < size; ++i) {
      int j1 = lower_bound(xcoor.begin(), xcoor.end(), recs[i].ltx) - xcoor.begin();
      int j2 = upper_bound(xcoor.begin(), xcoor.end(), recs[i].rdx) - xcoor.begin();
      for (j = j1; j <= j2 -2; ++j) {
        inters[j].push_back( Inte(recs[i].rdy, recs[i].lty));
      }
    }
    double res = calArea(inters, xcoor);
    return res;
  }
};
int main()
{
  Solution s;
  freopen("E://test.txt","r",stdin);
  vector<Rec> recs;
  int k, count = 0;
  double x1, x2, y1, y2;
  while (scanf("%d", &k) && k != 0) {
    recs.resize(0);
    printf("Test case #%d\n", ++count);
    while (k--) {
      scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
      recs.push_back(Rec(x1, y2, x2, y1));
    }
    double res = s.calAllArea(recs);
    printf("Total explored area: %.2f\n\n", res);    
  }
  return 0;
}

Another code using segment tree from :

http://blog.csdn.net/youngyangyang04/article/details/7787693


我的扫面线第一题,一开始看网上讲的都好抽象,最后还是研究别人代码整明白的,所以我要写一个直观的,哈哈哈!!希望大家都能看懂

如图虚线将整个图型分成三个矩形,我们现将每个点的x进行排序,也就是(10,15,20,25.5)

这样就知道矩形的长了,还差宽,然后我们就要开始扫描线啦

先每个点的y值离散话,因为我们要求的是映射在x轴的线段,然后建树,共有t哥点,样立t-1等于4

下面的线段树我每个离散花后的点对应的y值我都标记上了

将一号边加入线段,先加入一号边,二号边三号边四号边具体过程建议自己模拟一下

我每个线段树的点用s标记这条边被覆盖还是没被都盖,每条边的flag表示这天边是入度还是出度

注意啊!!我这个图x,y轴画反啦



#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 300
struct Node{
    double x;double y1;double y2;
    int flag;
}node[N];
bool cmp(Node a,Node b){
    return a.x-b.x<0.0000001;
}
double y[N];
struct node{
    int l;int r;double ml;double mr;int s;double len;
}a[N*3];
void build(int i,int left,int right){
    a[i].l=left;
    a[i].r=right;
    a[i].ml=y[left];
    a[i].mr=y[right];
    a[i].s=0;
    a[i].len=0;
    if(a[i].l+1==a[i].r){
        return ;
    }
    int mid=(left+right)>>1;
    build(i*2,left,mid);
    build(i*2+1,mid,right);//建树时注意这里不是mid+1,因为做相减的时候如果mid+1这么建回到值左孩子的右边与有孩子的左边无法进行运算
}
void callen(int i){

    if(a[i].s>0){//注意这里不是所有边都是左孩子的长度加上右孩子的长度,他存在一个覆盖问题
        a[i].len=a[i].mr-a[i].ml;
    }else if(a[i].r-a[i].l==1){
        a[i].len=0;
    }else{
        a[i].len=a[i*2].len+a[i*2+1].len;
    }
    return ;
}
void updata(int i,Node b){
    if(a[i].ml==b.y1&&a[i].mr==b.y2){
        a[i].s+=b.flag;
        callen(i);
        return ;
    }
    if(b.y2<=a[i*2].mr) updata(i*2,b);
    else if(b.y1>=a[i*2+1].ml) updata(i*2+1,b);
    else{
        Node temp=b;
        temp.y2=a[i*2].mr;
        updata(i*2,temp);
        temp=b;
        temp.y1=a[i*2+1].ml;
        updata(i*2+1,temp);
    }
    callen(i);
    return ;
}
int main(){
//    freopen("in.txt","r",stdin);
    int n,t,p=1,te;
    double x1,x2,y1,y2;
    while(scanf("%d",&n),n){
            t=1;
            for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            node[t].x=x1;
            node[t].y1=y1;
            node[t].y2=y2;
            node[t].flag=1;//入边
            y[t++]=y1;
            node[t].x=x2;
            node[t].y1=y1;
            node[t].y2=y2;
            node[t].flag=-1;//出边
            y[t++]=y2;
        }
        sort(node+1,node+t,cmp);
        sort(y+1,y+t);
        build(1,1,t-1);
        updata(1,node[1]);
        double sum=0;
        for(int i=2;i<t;i++){
            sum+=a[1].len*(node[i].x-node[i-1].x);
            updata(1,node[i]);
        }
        printf("Test case #%d\n",p++);
        printf("Total explored area: %.2lf\n\n",sum);
    }
    return 0;
}

Maybe for an interview:

#include <iostream>

class TNode {
 public:
  int l, r, s, len;
  double ll, rr;
  TNode *lc, *rc;
  TNode(int l1 = 0, int r1 = 0, int s1 = 0, int len1 = 0, double ll1 = 0, double rr1 = 0): l(l1), r(r1), s(s1), ll(ll1), rr(rr1), len(len1), lc(NULL), rc(NULL){}
};
class Rec {
 public:
  double ldx, ldy, rtx, rty;
  Rec(double ldx1 = 0, double ldy1 = 0, double rtx1 = 0, double rty1 = 0): ldx(ldx1), ldy(ldy1), rtx(rtx1), rty(rty1) {}
};
class Seg {
 public:
  double x, y1, y2;
  int dir;
  Seg(double x1 = 0, double yy1 = 0, double yy2 = 0, int dir1 = 0):x(x1), y1(yy1), y2(yy2), dir(dir1){}
};
class cmp {
 public:
  bool operator() (Seg& seg1, Seg& seg2) {
    return seg1.x < seg2.x;
  }
};

TNode* build(int l, int r, vector<int>& ysort) {
  TNode* rt = new TNode(l, r, 0, 0, ysort[l], ysort[r]);
  if (l + 1 >= r)
    return rt;
  int mid = (l + r) >> 1;
  rt->lc = new Tnode(l, mid, 0, 0, ysort[l], ysort[mid]);
  rt->rc = new Tnode(mid, r, 0, 0, ysort[mid], ysort[r]);
  return rt;
}

void cal(TNode* rt) {
  if (rt->s > 0) 
    rt->len += rt->rr-rt->ll;
  else if (rt->l + 1 = rt->r)
    rt->len = 0;
  else
    rt->len = rt->lc->len + rt->rc->len;    
}

void update(TNode* rt, Seg &seg) {
  if (rt->ll == seg.y1 && rt->rr == seg.y2) {
    rt->s += seg.dir;
    cal(rt);
  }
  else if (seg.y2 <= rt->lc->rr)
    update(rt->lc, seg);
  else if (seg.y1 >= rt->rc->ll)
    update(rt->rc, seg);
  else {
    Seg tmp = seg;
    tmp.y2 = rt->lc->rr;
    update(rt->lc, tmp);
    tmp = seg, tmp.y1 = rt->rc->ll;
    update(rt->rc, tmp);
  }
  cal(rt);
}
int calArea(vector<Rec>& recs) {
  vector<Seg> segs;
  vector<int> ysort;
  int i, size = recs.size(), l = 0, r = size-1;
  
  for (i = 0; i < size; ++i) {
    ysort.push_back(recs[i].ldx);
    ysort.push_back(recs[i].rtx);
    segs.push_back(Seg(recs[i].ldx, recs[i].ldy, recs[i].rty, 1));
    segs.push_back(Seg(recs[i].rtx, recs[i].ldy, recs[i].rty, -1));
  }
  sort(ysort.begin(), ysort.end());
  sort(segs.begin(), segs.end(), cmp());
  
  TNode *rt = build(l, r, ysort);
  update(rt, segs[0]);
  int res = 0;
  for (i = 1; i < size; ++i) {
    res += rt->len * (segs[i].x - segs[i-1].x);
    update(rt, segs[i]);
  }
  return res;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值