USACO Section 3.4 Closed Fences - 暴力枚举..


好恶心的题...断断续续作了三天才做出来...想吐了...试了N多方法..重写了N遍代码...终于让我给过了..

第一问很好做...只要判断下有没有两直线相交就行了..做两次差乘判断...

第二问我AC的思路是将每个线段给暴力离散化..离散为500个点..然后将每个点与视野点(x,y)做线段...若是有一个点做成的线段中间没有被其他线段所截断..那么就可判定所离散的线段是能够第一眼看到的..

首先我这个方法不够严谨...因为离散化这种方法本来就存在的细微的出错概率..离散得越细出错概率就越小...还有我的方法似乎一直没有考虑线段与视野点三点共线的情况...呃..弱爆了...不过AC了就好~~


Program:

/* ID: zzyzzy12 LANG: C++ TASK: fence4 */ #include<iostream> #include<istream> #include<stdio.h> #include<string.h> #include<math.h> #include<stack> #include<algorithm> #include<queue> #define oo 1000000000 #define ll long long #define pi (atan(2)+atan(0.5))*2 using namespace std; int n; double x,y; struct node1 { double x,y; }a[205]; struct node2 { double x1,y1,x2,y2; }line[205]; bool cross(node2 a,node2 b,int mode) { double x1,y1,x2,y2,s1,s2,p1,p2; x1=a.x1-b.x1; y1=a.y1-b.y1; x2=b.x2-b.x1; y2=b.y2-b.y1; s1=x1*y2-x2*y1; x1=a.x2-b.x1; y1=a.y2-b.y1; s2=x1*y2-x2*y1; p1=s1*s2; x1=b.x1-a.x1; y1=b.y1-a.y1; x2=a.x2-a.x1; y2=a.y2-a.y1; s1=x1*y2-x2*y1; x1=b.x2-a.x1; y1=b.y2-a.y1; s2=x1*y2-x2*y1; p2=s1*s2; if (!mode && p1<-0.000001 && p2<-0.000001) return true; if (mode && p1<0.000001 && p2<0.000001) return true; return false; } double abs_b(double x) { if (x<0) return -x; return x; } void getanswer() { int i,j,t,num=0; double len,k,min_x,max_x,max_y,min_y; line[1].x1=a[1].x; line[1].y1=a[1].y; line[1].x2=a[n].x; line[1].y2=a[n].y; bool can[205]; for (i=1;i<=n;i++) { line[i].x1=a[i].x; line[i].y1=a[i].y; line[i].x2=a[i+1].x; line[i].y2=a[i+1].y; for (j=1;j<i;j++) if (cross(line[i],line[j],0)) { printf("NOFENCE\n"); return; } } line[n]=line[n-1]; line[n-1].x1=a[1].x; line[n-1].y1=a[1].y; line[n-1].x2=a[n].x; line[n-1].y2=a[n].y; memset(can,false,sizeof(can)); line[0].x1=x; line[0].y1=y; for (i=1;i<=n;i++) { min_x=min(line[i].x1,line[i].x2); max_x=max(line[i].x1,line[i].x2); min_y=min(line[i].y1,line[i].y2); max_y=max(line[i].y1,line[i].y2); if (abs_b(max_x-min_x)>0.01) { len=(max_x-min_x)/500; for (k=min_x;k<=max_x;k+=len) { line[0].x2=k; line[0].y2=(k-line[i].x1)*(line[i].y2-line[i].y1)/(line[i].x2-line[i].x1)+line[i].y1; for (j=1;j<=n;j++) if (j!=i && cross(line[j],line[0],1)) goto A; if (!can[i]) num++; can[i]=true; A: ; if (can[i]) goto C; } }else { len=(max_y-min_y)/500; for (k=min_y;k<=max_y;k+=len) { line[0].y2=k; line[0].x2=(k-line[i].y1)*(line[i].x2-line[i].x1)/(line[i].y2-line[i].y1)+line[i].x1; for (j=1;j<=n;j++) if (j!=i && cross(line[j],line[0],1)) goto B; if (!can[i]) num++; can[i]=true; B: ; if (can[i]) goto C; } } C: ; } printf("%d\n",num); for (i=1;i<=n;i++) if (can[i]) printf("%.0lf %.0lf %.0lf %.0lf\n",line[i].x1,line[i].y1,line[i].x2,line[i].y2); } int main() { freopen("fence4.in","r",stdin); freopen("fence4.out","w",stdout); scanf("%d%lf%lf",&n,&x,&y); for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y); a[0]=a[n]; a[n+1]=a[1]; getanswer(); return 0; }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值