POJ 2706 Connect BFS + 判断线段相交
来源:互联网 发布:java生成excel报表 编辑:程序博客网 时间:2024/06/07 10:44
题意:在n*n的棋盘上有依次放上m个棋子。黑子先手。判断最后一个黑子所连成的线段能否贯穿其区域。
若两颗子中间已有直线存在(端点除外),则此两子不能连。且在最后一个黑子之前,不存在黑子连线贯穿整个区域的情况。
判断两线段相交:
因为此题不存在水平线段或者数值线段,所以可以丧心病狂的使用斜率。
设t1,t2为等待被连线的两个点,该线段所在直线斜率为k1,截距为b;
设t3,t4为有可能阻断t1,t2连线的两个点,其所在的斜率亦为k1的直线的截距为b2.b3;
若b,b2,b3满足 (b2 < b < b3) || (b2 > b > b3) 则说明t3,t4所在直线与t1,t2所在直线相交。
然此题是线段,所以还需加限制条件。
如下图:
只需在符合两直线相交的情况下判断两点均在黑线所围成的区域能即可。
剩下的就是简单的BFS了,不再赘述。
#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <cmath>#include <algorithm>using namespace std;struct C{ int x,y; C *next;}*head[25][25];struct P{ int x,y;};C *creat(){ C *p = (C *)malloc(sizeof(C)); p->next = NULL; return p;}int mc[25][25];int jx[] = {-2,-2,-1, 1, 2, 2, 1,-1};//八个方向int jy[] = {-1, 1, 2, 2, 1,-1,-2,-2};bool checkC(int x1,int y1,int x2,int y2)//检查与(x1,y1)相连的点中有木有(x2,y2);{ for(C *p = head[x1][y1]->next;p != NULL; p = p->next) { if(p->x == x2 && p->y == y2) return true; } return false;}bool judgeinc(int minx,int maxx,int miny,int maxy,int x,int y,int n)//检查(x,y)是否在黑线所围成的区域内{ int minx1, maxx1, miny1, maxy1; minx1 = minx-1 >= 0 ? minx-1 : 0; maxx1 = maxx+1 <= n ? maxx+1 : n; miny1 = miny-1 >= 0 ? miny-1 : 0; maxy1 = maxy+1 <= n ? maxy+1 : n; int i,j; for(i = minx1;i <= maxx1; ++i) { for(j = miny;j <= maxy; ++j) { if(i == x && j == y) return true; } } for(i = minx;i <= maxx; ++i) { for(j = miny1;j <= maxy1; ++j) { if(i == x && j == y) return true; } } return false;}bool judgeC(P t1,P t2,int n)//判断两点之间是否有线段阻隔{ int minx,miny,maxx,maxy; P temp; minx = (t1.x < t2.x ? t1.x : t2.x); maxx = (t1.x > t2.x ? t1.x : t2.x); miny = (t1.y < t2.y ? t1.y : t2.y); maxy = (t1.y > t2.y ? t1.y : t2.y); double k,b,b1,b2; int i,j,u; k = (t2.y-t1.y)*1.0/(t2.x-t1.x); b = t2.y*1.0 - k*t2.x; //实际上只需要检查与t1,t2在同一 ‘日’ 字内的其余四个点 for(i = minx;i <= maxx; ++i) { for(j = miny;j <= maxy; ++j) { if( !( (i == t1.x && j == t1.y) || (i == t2.x && j == t2.y) ) ) { b1 = j*1.0 - k*i; for(u = 0;u < 8;++u) { temp.x = i+jx[u]; temp.y = j+jy[u]; if(0 <= temp.x && temp.y <= n && 0 <= temp.y && temp.y <= n) { b2 = temp.y*1.0 - k*temp.x; if( ( (b1 > b && b > b2) || (b1 < b && b < b2) ) && judgeinc(minx,maxx,miny,maxy,temp.x,temp.y,n) && checkC(i,j,temp.x,temp.y) ) return false; } } } } } return true;}void link(P t1,P t2)//将t2插入t1的链表内 说明二者可连接{ C *p = head[t1.x][t1.y]; C *q = creat(); q->x = t2.x; q->y = t2.y; q->next = p->next; p->next = q;}void connect(int x,int y,int type,int n){ int i; P t1,t2; t1.x = x; t1.y = y; for(i = 0;i < 8; ++i) { t2.x = t1.x+jx[i]; t2.y = t1.y+jy[i]; if(0 <= t2.x && t2.x <= n && 0 <= t2.y && t2.y <= n && mc[t2.x][t2.y] == type && judgeC(t1,t2,n)) { link(t1,t2); link(t2,t1); } }}bool MarkVisit[25][25];bool judge(int x,int y,int n)//判断最后是否胜利{ queue<P> q; memset(MarkVisit,false,sizeof(MarkVisit)); P t1,t2; t1.x = x; t1.y = y; q.push(t1); MarkVisit[x][y] = true; bool m1 = false,m2 = false; C *p; while(q.empty() == false && (m1 == false || m2 == false)) { t1 = q.front(); q.pop(); if(t1.y == 0) m1 = true; if(t1.y == n) m2 = true; for(p = head[t1.x][t1.y]->next; p != NULL ; p = p->next) { t2.x = p->x; t2.y = p->y; if(MarkVisit[t2.x][t2.y] == false) { q.push(t2); MarkVisit[t2.x][t2.y] = true; } } } if(m1 && m2) return true; return false;}int main(){ int n,m; int i,j; int x,y; int step; n = 22; for(i = 0; i <= n; ++i) { for(j = 0; j <= n; ++j) { head[i][j] = creat(); } } while(scanf("%d %d",&n,&m) && (n||m)) { for(i = 0; i <= n; ++i) { for(j = 0; j <= n; ++j) { mc[i][j] = 0; head[i][j]->next = NULL; } } for(step = 1; step <= m; ++step) { scanf("%d %d",&y,&x); if(step&1) { mc[x][y] = 1; connect(x,y,1,n); } else { mc[x][y] = 2; connect(x,y,2,n); } } if(judge(x,y,n)) cout<<"yes"<<endl; else cout<<"no" <<endl; } return 0;}
- POJ 2706 Connect BFS + 判断线段相交
- POJ 1066 判断线段相交
- POJ 1066 线段相交判断
- POJ 2653 判断线段相交
- POJ 2653 判断线段相交
- POJ 2653 (判断线段相交)
- poj 1410 矩形与线段相交判断
- poj 1066 Treasure Hunt(判断线段相交)
- POJ 2653 暴力判断线段相交
- POJ 3304 判断直线与线段相交
- POJ 3304 判断线段 与 直线 相交
- poj 3304-Segments 线段相交的判断
- poj 3304 判断直线与线段相交
- POJ 3304 判断线段相交(叉积)
- POJ 2653 线段相交判断 (叉积)
- POJ 3304 判断线段和直线相交
- poj 1410 Intersection(线段相交判断)
- POJ 3304 直线与线段相交判断
- 【初学】Objective-C学习笔记-委托代理(delegate)和协议(protocol)
- vhost
- [C++]MySQL数据库操作实例
- linux 超级终端 minicom使用手册
- ogre读取图片
- POJ 2706 Connect BFS + 判断线段相交
- 死锁与活锁
- java heap space eclipse
- Install sun-java5-jdk to Ubuntu 10.04
- Qt 发送 https 请求
- C语言除法运算符“/”和求余运算符“%”
- 二级指针和函数参数——指针参数是如何传递内存的?
- svn冲突解决
- 【动态规划】买票找零