【做题笔记】SP5463 BIRD - Bird or not bird
Problem
SP5463 BIRD - Bird or not bird
题目大意:
已知若一只动物是鸟,则它的身高在一个区间内,体重在另一个区间内。且若一只动物的身高和体重都在相应的区间内,则它一定是鸟。
给你 \(n\) 只动物的身高和体重并告诉你它们是不是鸟。
然后又给你 \(m\) 只动物的身高和体重,请你回答它们是不是鸟,或者回答你不能确定它们是不是鸟。
Solution
对于那 \(n\) 只动物,显然可以对是鸟的和不是鸟的分开处理,身高和体重分开处理。
对于是鸟的:
对于身高,取一个最大值和一个最小值,构成已知的鸟的身高区间。体重也一样。
对于不是鸟的:
若其中一个值(这里以体重为例)在鸟的区间中,则另一个值(身高)一定不在鸟的区间中。在满足条件的所有数据中,取一个最大身高,它比鸟的身高区间的最小值还要小。再取一个最小身高,它比鸟的身高区间的最大值还要大。
于是对于身高和体重,都会变成下面这种情况:
但是!在不是鸟的动物中,如果身高体重没有一个满足在鸟的区间内,这些动物还没有被使用过。
假设有一个满足上面条件的动物 \(i\),它的身高和体重分别为 \(h_i,w_i\)。
另有一个待判断的动物 \(j\),它的身高和体重分别为 \(h_j,w_j\),且已经判定它要么是 NOT BIRD
,要么是 UNKNOWN
。
设已知的鸟的身高区间为 \([HL,HR]\),体重区间为 \([WL,WR]\)。
如果它们满足如下两种情况:
- \(h_j \le h_i < HL\) 或 \(h_j \ge h_i > HR\)。
- \(w_j \le w_i < WL\) 或 \(w_j \ge w_i > WR\)。
可不可以判定它是 NOT BIRD
?可以。因为已知 \(i\) 要么身高不符合要求,要么体重不符合要求,且无论 \(i\) 是身高不符合要求还是体重不符合要求,最终都可以推断出 \(j\) 不是鸟。
另外还有一个注意点,如果给的 \(n\) 只动物中没有 BIRD
,那么对于询问,判断一下身高体重与前 \(n\) 只动物有没有完全相同的,有则 NOT BIRD
,否则为 UNKNOWN
。(虽然直接输出 UNKNOWN
也能对(雾))
Code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int T,n,m,cnt,h[1005],w[1005];
//h,w 为前 n 只动物中 NOT BIRD 的动物的身高和体重,cnt 为它们的数量。
int bhl,bhr,bwl,bwr,nhr,nhl,nwr,nwl;
//[bhl,bhr] 为可以确定的鸟的身高区间。
//[bwl,bwr] 为可以确定的鸟的体重区间。
//nhr 为身高中左边的 NOTBIRD 的最大值。
//nhl 为身高中右边的 NOTBIRD 的最小值。
//nwr 为体重中左边的 NOTBIRD 的最大值。
//nwl 为体重中右边的 NOTBIRD 的最小值。
int num,H[1005],W[1005];
//H,W 为身高和体重都不在[bhl,bhr],[bwl,bwr] 中的鸟的身高和体重,num为它们的数量。
int main()
{
scanf("%d",&T);
for(int Case=1;Case<=T;Case++)
{
scanf("%d",&n);cnt=0;
bhl=bwl=nhl=nwl=1e6+1;bhr=bwr=nhr=nwr=0;
for(int i=1;i<=n;i++)
{
int hh,ww;
scanf("%d%d",&hh,&ww);
string s;
cin>>s;
if(s=="BIRD")
{
bhl=min(bhl,hh);
bhr=max(bhr,hh);
bwl=min(bwl,ww);
bwr=max(bwr,ww);
//以上为求 bhl,bhr,bwl,bwr。
}
else{cin>>s;cnt++;h[cnt]=hh,w[cnt]=ww;}
}
num=0;
for(int i=1;i<=cnt;i++)
{
int flag=0;
if(h[i]<bhl&&bwl<=w[i]&&w[i]<=bwr) nhr=max(nhr,h[i]),flag=1;
if(h[i]>bhl&&bwl<=w[i]&&w[i]<=bwr) nhl=min(nhl,h[i]),flag=1;
if(w[i]<bwl&&bhl<=h[i]&&h[i]<=bhr) nwr=max(nwr,w[i]),flag=1;
if(w[i]>bwl&&bhl<=h[i]&&h[i]<=bhr) nwl=min(nwl,w[i]),flag=1;
//以上为求nhr,nhl,nwr,nwl。
if(!flag){num++;H[num]=h[i];W[num]=w[i];}
}
printf("Case #%d:\n",Case);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int qh,qw;
scanf("%d%d",&qh,&qw);
if(cnt!=n)
{
if(bhl<=qh&&qh<=bhr&&bwl<=qw&&qw<=bwr) puts("BIRD");
else if(qh<=nhr||qh>=nhl||qw<=nwr||qw>=nwl) puts("NOT BIRD");
else
{
for(int i=1;i<=num;i++)
{
int f1=(H[i]<=bhl)?(qh<=H[i]):(qh>=H[i]);
int f2=(W[i]<=bwl)?(qw<=W[i]):(qw>=W[i]);
if(f1&&f2){puts("NOT BIRD");goto FINISH;}
}
//以上为另一种 NOT BIRD 的情况。
puts("UNKNOWN");
FINISH:;
}
}
else//前 n 只动物中没有 BIRD。
{
for(int j=1;j<=n;j++)
if(qh==h[j]&&qw==w[j]){puts("NOT BIRD");goto END;}
puts("UNKNOWN");
END:;
}
}
}
return 0;
}