usaco3.1.5形成的区域

76 篇文章 0 订阅

漂浮法

以逆序来进行放置,即n to 1。逆序的好处在于放置一个矩形后,俯视看到的就是最终俯视该矩形应该看到的。因为挡着它的矩形在之前已经放置好了,所以可直接统计,为递归创造了条件。每放一个矩形,可以想象成将其扔入一密度很大的海水底部,海分成了n层,然后矩形开始向上浮。在上浮过程中若碰撞到其他的矩形则断裂成几个小矩形,继续上浮,直到浮出水面。于是想到用个递归来模拟上浮过程。

procedure cover(l,r,s,d,k,col:integer);
  begin
    while (k<=n) and ((r<=x1[k]) or (l>=x2[k]) or (d<=y1[k]) or (s>=y2[k])) do
      inc(k);
    if k>n then begin ans[col]:=ans[col]+(r-l)*(d-s); exit; end;
    if l<=x1[k] then begin cover(l,x1[k],s,d,k+1,col); l:=x1[k]; end;
    if r>=x2[k] then begin cover(x2[k],r,s,d,k+1,col); r:=x2[k]; end;
    if s<=y1[k] then begin cover(l,r,s,y1[k],k+1,col); s:=y1[k]; end;
    if d>=y2[k] then begin cover(l,r,y2[k],d,k+1,col); d:=y2[k]; end;
  end;
(主要是对于这一题没有深刻的理解,如果对图能更好的深入透析,这就写得出来了。这个方法速度很快)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
int ans[3000],n;
struct sfaf{int x1;int y1;int x2;int y2;int color;}tu[1010];
void piaofu(int x1,int x2,int y1,int y2,int k,int col);
int main()
{
    //freopen("rect1.in","r",stdin);
    //freopen("rect1.out","w",stdout);
    cin>>tu[0].x2>>tu[0].y2>>n;
    tu[0].color=1;
    for(int i=1;i<=n;i++)
    {
        cin>>tu[i].x1>>tu[i].y1>>tu[i].x2>>tu[i].y2>>tu[i].color;
    }
    for(int i=n;i>=0;i--){
        piaofu(tu[i].x1,tu[i].x2,tu[i].y1,tu[i].y2,i+1,tu[i].color);
    }
    for(int i=1;i<=2500;i++)
        if(ans[i]!=0)cout<<i<<" "<<ans[i]<<endl;
return 0;
}
void piaofu(int x1,int x2,int y1,int y2,int k,int col)
{
    while((x1>=tu[k].x2||x2<=tu[k].x1||y1>=tu[k].y2||y2<=tu[k].y1)&&k<=n)k++;
    if(k==n+1){ans[col]+=(x2-x1)*(y2-y1);return;}
    if(x1<tu[k].x1){piaofu(x1,tu[k].x1,y1,y2,k+1,col);x1=tu[k].x1;}
    if(x2>tu[k].x2){piaofu(tu[k].x2,x2,y1,y2,k+1,col);x2=tu[k].x2;}
    if(y1<tu[k].y1){piaofu(x1,x2,y1,tu[k].y1,k+1,col);y1=tu[k].y1;}
    if(y2>tu[k].y2){piaofu(x1,x2,tu[k].y2,y2,k+1,col);y2=tu[k].y2;}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值