BZOJ1074: [SCOI2007]折纸origami

很裸的一道计算几何对吧
每一个询问我们就只需要易操作将他展开就好了。。
很显然爆搜中可以删几个不可能的中途状态点
时间上界是 2nm
然后我是在linux打的。。。调戏了很久毛了搬到Windows上才发现是一个double打成了int。。。。。各种不爽

#include<cstdio>
#include<iostream>
#include<cstdio>
#include<set>
using namespace std;

inline double abs(double a){return a<0?-a:a;}



const
   double eps=0.000001;

struct Point
{
   double x,y;
   inline friend bool operator ==(Point a,Point b) { 
         return abs(a.x-b.x)<eps&&abs(a.y-b.y)<eps;
 } 
};
const 
  int INF=1<<29;
const Point Wa=(Point){-INF,-INF};
const Point Single=(Point){INF,INF};
struct Line
{
   Point start,end;
};
inline double Cross(Point a,Point b)
{return a.x*b.y-a.y*b.x;}

inline Point Rotato(Point a,Line b)
{
      Point tpa,tpb;
     tpa.x=a.x-b.start.x;
     tpa.y=a.y-b.start.y;
     tpb.x=b.end.x-b.start.x;
     tpb.y=b.end.y-b.start.y;
       Point res;
     if(Cross(tpb,tpa)>eps)
         {
           if(abs(b.start.x-b.end.x)<eps)
                    res.x=2*b.start.x-a.x,res.y=a.y;
            else if(abs(b.start.y-b.end.y)<eps)
                    res.x=a.x,res.y=2*b.start.y-a.y;
            else
                 {
                    double k=b.end.y-b.start.y,k1;
                    k/=b.end.x-b.start.x;
                    k1=-1/k;double b1=b.end.x*b.start.y-b.end.y*b.start.x,b2;
                    b1/=b.end.x-b.start.x;
                    if(abs(a.x)<eps)b2=a.y;
                    else b2=a.y-k1*a.x;
                    res.x=(b2-b1)/(k-k1);res.y=k*res.x+b1;
                    res.x*=2,res.y*=2,res.x-=a.x,res.y-=a.y;
                  }
            return res;
          }
    if(Cross(tpb,tpa)<-eps)
    return Wa;
    return Wa;
}
Line Oper[10001];
int ans;
int n;

inline bool Can(Point a)
{return a.x>eps&&a.x<100-eps&&a.y>eps&&a.y<100-eps;}
void DFS(Point a,int t)
{
       Point fl;
      if(t==0)
        {if(Can(a))ans++;return ;}
      fl=Rotato(a,Oper[t])     ;
      if(fl==Wa)return;
      else if(fl==Single)DFS(a,t-1);
      else DFS(fl,t-1),DFS(a,t-1);
}

int main()
{
  int n,m;scanf("%d",&n);
  for(int i=1;i<=n;i++) 
     scanf("%lf",&Oper[i].start.x),
     scanf("%lf",&Oper[i].start.y),
     scanf("%lf",&Oper[i].end.x),
     scanf("%lf",&Oper[i].end.y);
  scanf("%d",&m);
  for(int i=1;i<=m;i++)
        {
            Point re;ans=0;
           scanf("%lf%lf",&re.x,&re.y);

           DFS(re,n);
           printf("%d\n",ans);
         }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值