您的位置:首页 > 其它

UVALive 4639 - Separate Points

2012-08-16 21:04 363 查看
Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld
& %llu
Submit Status Practice UVALive
4639

Description





Numbers of black and white points are placed on a plane. Let's imagine that a straight line of infinite length is drawn on the plane. When the line does not meet any of the points, the line divides these points
into two groups. If the division by such a line results in one group consisting only of black points and the other consisting only of white points, we say that the line ``separates black and white points".
Let's see examples in Figure 3. In the leftmost example, you can easily find that the black and white points can be perfectly separated by the dashed line according to their colors. In the remaining three examples,
there exists no such straight line that gives such a separation.



[align=center]Figure 3: Example planes[/align]
In this problem, given a set of points with their colors and positions, you are requested to decide whether there exists a straight line that separates black and white points.

Input

The input is a sequence of datasets, each of which is formatted as follows.

n m 

x1 y1 

... 
xn yn 
xn+1 yn+1 

... 
xn+m yn+m

The first line contains two positive integers separated by a single space; n is the number of black points, and m is the number of white points. They are less than or equal to 100. Then n + m lines
representing the coordinates of points follow. Each line contains two integersxi and yi separated by a space, where (xi, yi) represents
the x-coordinate and the y-coordinate of the i-th point. The color of the i-th point is black for 1

i

n,
and is white for n + 1

i

n + m.
All the points have integral x- and y-coordinate values between 0 and 10000 inclusive. You can also assume that no two points have the same
position.
The end of the input is indicated by a line containing two zeros separated by a space.

Output

For each dataset, output ``YES" if there exists a line satisfying the condition. If not, output ``NO". In either case, print it in one line for each input dataset.

Sample Input

3 3
100 700
200 200
600 600
500 100
500 300
800 500
3 3
100 300
400 600
400 100
600 400
500 900
300 300
3 4
300 300
500 300
400 600
100 100
200 900
500 900
800 100
1 2
300 300
100 100
500 500
1 1
100 100
200 100
2 2
0 0
500 700
1000 1400
1500 2100
2 2
0 0
1000 1000
1000 0
0 1000
3 3
0 100
4999 102
10000 103
5001 102
10000 102
0 101
3 3
100 100
200 100
100 200
0 0
400 0
0 400
3 3
2813 1640
2583 2892
2967 1916
541 3562
9298 3686
7443 7921
0 0


Sample Output

YES
NO
NO
NO
YES
YES
NO
NO
NO
YES


比赛时,WA了三遍的题。大体思路比较简单,但细节比较纠结,就是在黑点和白点中任意取两点组成一条直线,只要可以将白点和黑点分成两部分则具备一条直线可以将其分成黑白两部分,但当所有点都在一条直线上时需要特殊处理(按x值排序比较黑白临界点大小)。

比赛时的代码(跑了1s多):

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
struct point
{
double x, y;
} b[105], w[105];
int cmp(const void *a, const void *b)
{
point *aa = (point *)a;
point *bb = (point *)b;
if(aa->x != bb->x)
return aa->x > bb->x ? 1 : -1;
return aa->y > bb->y ? 1 : -1;
}
const double eps = 1e-12;
int main()
{
int m,n;
while(cin>>m>>n)
{
if(!m&&!n)break;
for(int i=0; i<m; i++)
cin>>b[i].x>>b[i].y;
for(int i=0; i<n; i++)
cin>>w[i].x>>w[i].y;
qsort(b, m, sizeof(b[0]), cmp);
qsort(w, n, sizeof(w[0]), cmp);
int flag=0, cct, fflag = 0;
for(int i = 0; i < m; i++) // 先检验黑点
{
for(int j =  i + 1; j < m; j++)
{
cct = 0;
int ll = 0, rr = 0, ll2 = 0, rr2 = 0;
if(!(fabs(b[i].x - b[j].x) < eps))
{
double k = (b[i].y - b[j].y) / (b[i].x - b[j].x);
double bb =  b[i].y - k * b[i].x;
for(int kk = 0; kk < n; kk++)
if(w[kk].y - k * w[kk].x - bb < -eps)
++rr;
else if(w[kk].y - k * w[kk].x - bb > eps)
++ll;
else if(fabs(w[kk].y - k * w[kk].x - bb) < eps)
++cct;
for(int kk = 0; kk < m; kk++)
if(kk != i && kk != j)
{
if(b[kk].y - k * b[kk].x - bb < -eps)
++rr2;
else if(b[kk].y - k * b[kk].x - bb > eps)
++ll2;
else if(fabs(b[kk].y - k * b[kk].x - bb) < eps)
++cct;
}
}
else // 注意垂直直线的处理
{

for(int kk = 0; kk < n; kk++)
if(w[kk].x < b[j].x)
++rr;
else if(w[kk].x > b[j].x)
++ll;

for(int kk = 0; kk < m; kk++)
if(kk != i && kk != j)
{
if(b[kk].x < b[j].x)
++rr2;
else if(b[kk].x > b[j].x)
++ll2;
}
}
if(cct == m + n - 2)
{
fflag = 1;
break;
}
if((ll == n && !ll2) || (rr == n && !rr2))
{
flag = 1;
break;
}
}
if(flag)
break;
}
if(!flag && ! fflag) // 检验白点
{
for(int i = 0; i < n; i++)
{
for(int j =  i + 1; j < n; j++)
{
int ll = 0, rr = 0, ll2 = 0, rr2 = 0;
if(!(fabs(w[i].x - w[j].x) < eps))
{
double k = (w[i].y - w[j].y) / (w[i].x - w[j].x);
double bb =  w[i].y - k * w[i].x;
for(int kk = 0; kk < m; kk++)
if(b[kk].y - k * b[kk].x - bb < -eps)
++rr;
else if(b[kk].y - k * b[kk].x - bb > eps)
++ll;
for(int kk = 0; kk < n; kk++)
if(kk != i && kk != j)
{
if(w[kk].y - k * w[kk].x - bb < -eps)
++rr2;
else if(w[kk].y - k * w[kk].x - bb > eps)
++ll2;
}
}
else
{

for(int kk = 0; kk < m; kk++)
if(b[kk].x < w[j].x)
++rr;
else if(b[kk].x > w[j].x)
++ll;
for(int kk = 0; kk < n; kk++)
if(kk != i && kk != j)
{
if(w[kk].x < w[j].x)
++rr2;
else if(w[kk].x > w[j].x)
++ll2;
}

}
if((ll == m && !ll2) || (rr == m && !rr2))
{

flag = 1;
break;
}
}
if(flag)
break;
}
}
if(fabs(b[0].x - b[m - 1].x) < eps && fabs(w[0].x - w[n - 1].x) < eps && fabs(b[0].x - w[0].x) < eps) // 所有点在一条垂直直线时,特殊处理
{
if(b[m - 1].y < w[0].y || w[n - 1].y < b[0].y)
flag = 1;
}
if(fflag) // 所有点在一条斜线时,特殊处理
{
if(b[m - 1].x < w[0].x || w[n - 1].x < b[0].x)
flag = 1;
}
if(flag == 1||(m==1&&n==1))cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}


比赛完又大体剪了一下枝,时间减到280ms,但代码却已出奇的长了,抽空再建子函数缩一下代码吧,今儿个实在累了。

粗减之后的代码:

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;

struct point
{
double x, y;
} b[105], w[105];
int cmp(const void *a, const void *b)
{
point *aa = (point *)a;
point *bb = (point *)b;
if(aa->x != bb->x)
return aa->x > bb->x ? 1 : -1;
return aa->y > bb->y ? 1 : -1;
}
const double eps = 1e-12;
int main()
{
freopen("in.txt", "r", stdin);
int m,n;
while(cin>>m>>n)
{
if(!m&&!n)break;
for(int i=0; i<m; i++)
cin>>b[i].x>>b[i].y;
for(int i=0; i<n; i++)
cin>>w[i].x>>w[i].y;
qsort(b, m, sizeof(b[0]), cmp);
qsort(w, n, sizeof(w[0]), cmp);
int flag=0, cct, fflag = 0;
for(int i = 0; i < m; i++)
{
for(int j =  i + 1; j < m; j++)
{
cct = 0;
int ll = 0, rr = 0, ll2 = 0, rr2 = 0;
if(!(fabs(b[i].x - b[j].x) < eps))
{
int flag_l = 0, flag_r = 0;
double k = (b[i].y - b[j].y) / (b[i].x - b[j].x);
double bb =  b[i].y - k * b[i].x;
for(int kk = 0; kk < n; kk++)
{
if(w[kk].y - k * w[kk].x - bb < -eps)
{
++rr;
flag_l = 1;
}
else if(w[kk].y - k * w[kk].x - bb > eps)
{
++ll;
flag_r = 1;
}
else if(fabs(w[kk].y - k * w[kk].x - bb) < eps)
++cct;
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r) // 加了许多诸如此类的粗剪枝
continue;
flag_l = 0, flag_r = 0;
for(int kk = 0; kk < m; kk++)
if(kk != i && kk != j)
{
if(b[kk].y - k * b[kk].x - bb < -eps)
{
++rr2;
flag_r = 1;
}
else if(b[kk].y - k * b[kk].x - bb > eps)
{
++ll2;
flag_l = 1;
}
else if(fabs(b[kk].y - k * b[kk].x - bb) < eps)
++cct;
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r)
continue;
}
else
{
int flag_l = 0, flag_r = 0;
for(int kk = 0; kk < n; kk++)
{
if(w[kk].x < b[j].x)
{
flag_r = 1;
++rr;
}
else if(w[kk].x > b[j].x)
{
flag_l = 1;
++ll;
}
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r)
continue;
flag_l = 0, flag_r = 0;
for(int kk = 0; kk < m; kk++)
if(kk != i && kk != j)
{
if(b[kk].x < b[j].x)
{
++rr2;
flag_r = 1;
}
else if(b[kk].x > b[j].x)
{
++ll2;
flag_l = 1;
}
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r)
continue;
}
if(cct == m + n - 2)
{
fflag = 1;
break;
}
if((ll == n && !ll2) || (rr == n && !rr2))
{
flag = 1;
break;
}
}

if(flag)
break;
}
if(!flag && ! fflag)
{
for(int i = 0; i < n; i++)
{
for(int j =  i + 1; j < n; j++)
{
int ll = 0, rr = 0, ll2 = 0, rr2 = 0;
if(!(fabs(w[i].x - w[j].x) < eps))
{
int flag_l = 0, flag_r = 0;
double k = (w[i].y - w[j].y) / (w[i].x - w[j].x);
double bb =  w[i].y - k * w[i].x;
for(int kk = 0; kk < m; kk++)
{
if(b[kk].y - k * b[kk].x - bb < -eps)
{
++rr;
flag_r = 1;
}
else if(b[kk].y - k * b[kk].x - bb > eps)
{
++ll;
flag_l = 1;
}
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r)
continue;
flag_l = 0, flag_r = 0;
for(int kk = 0; kk < n; kk++)
if(kk != i && kk != j)
{
if(w[kk].y - k * w[kk].x - bb < -eps)
{
++rr2;
flag_r = 1;
}
else if(w[kk].y - k * w[kk].x - bb > eps)
{
++ll2;
flag_l = 1;
}
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r)
continue;
}
else
{
int flag_l = 0, flag_r = 0;
for(int kk = 0; kk < m; kk++)
{

if(b[kk].x < w[j].x)
{
++rr;
flag_r = 1;
}
else if(b[kk].x > w[j].x)
{
++ll;
flag_l = 1;
}
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r)
continue;
flag_l = 0, flag_r = 0;
for(int kk = 0; kk < n; kk++)
if(kk != i && kk != j)
{
if(w[kk].x < w[j].x)
{
++rr2;
flag_r = 1;
}
else if(w[kk].x > w[j].x)
{
++ll2;
flag_l = 1;
}
if(flag_l && flag_r)
break;
}
if(flag_l && flag_r)
continue;

}
if((ll == m && !ll2) || (rr == m && !rr2))
{

flag = 1;
break;
}
}
if(flag)
break;
}
}
if(fabs(b[0].x - b[m - 1].x) < eps && fabs(w[0].x - w[n - 1].x) < eps && fabs(b[0].x - w[0].x) < eps)
{
if(b[m - 1].y < w[0].y || w[n - 1].y < b[0].y)
flag = 1;
}
if(fflag)
{
if(b[m - 1].x < w[0].x || w[n - 1].x < b[0].x)
flag = 1;
}
if(flag == 1||(m==1&&n==1))cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: