题意:在三维坐标上有n个战士和m个弓箭手,所有弓箭手朝同一方向射箭,问可以射中多少弓箭手( 箭不会停止);
思路:坐标映射,因为箭的方向是一定的,所以每个战士和弓箭手都可以确定一条直线:
x = a[i].x +k*v.x;
y = a[i].y +k*v.y;
z = a[i].z + k*v.z;
//a[i]为战士的坐标,v为箭的方向
令 x = 0;则可以求出 y 和z,只有y和z都相等的情况下两点的方向和箭的方向一样;
#include <stdio.h>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#define ll long long
using namespace std;
#define M 10010
struct Point
{
ll x, y, z;
}a[M], b[M], v;
struct Node
{
ll x, y, z;
int id;
friend bool operator == ( Node a, Node b )
{
return a.x == b.x && a.y == b.y;
}
}nde[M*2];
int n, m, cnt;
bool cmp( Node a, Node b )
{
if( a.x == b.x ){
if( a.y == b.y ){
if( a.z == b.z ) //相同的点
return a.id > b.id;//所以把弓箭手排在前面
return a.z < b.z; //确定方向的
}
else return a.y < b.y;
}
return a.x < b.x;
}
void init() //假如箭的x方向为0,则不能把直线映射到 x = 0这个面
{
if( v.x == 0 ){
if( v.y != 0 ){
swap( v.x, v.y );
for( int i = 0; i < n; i++ )
swap( a[i].x, a[i].y );
for( int i = 0; i < m; i++ )
swap( b[i].x, b[i].y );
}
else{
swap( v.x, v.z );
for( int i = 0; i < n; i++ )
swap( a[i].x, a[i].z );
for( int i = 0; i < m; i++ )
swap( b[i].x, b[i].z );
}
}
}
int main()
{
int t = 0, T, ans, k;
scanf( "%d", &T );
while( T-- ){
scanf( "%d%d", &n, &m );
for( int i = 0; i < n; i++ )
scanf( "%I64d%I64d%I64d", &a[i].x, &a[i].y, &a[i].z );
for( int i = 0; i < m; i++ )
scanf( "%I64d%I64d%I64d", &b[i].x, &b[i].y, &b[i].z );
scanf( "%I64d%I64d%I64d", &v.x, &v.y, &v.z );
init();
ans = cnt = 0;
for( int i = 0; i < n; i++ ){
nde[cnt].x = a[i].y*v.x - a[i].x*v.y;
nde[cnt].y = a[i].z*v.x - a[i].x*v.z;
if( v.x > 0 ) //需要根据箭的方向来排序
nde[cnt].z = a[i].x;
else nde[cnt].z = -a[i].x;
nde[cnt++].id = 0;
}
for( int i = 0; i < m; i++ ){
nde[cnt].x = b[i].y*v.x - b[i].x*v.y;
nde[cnt].y = b[i].z*v.x - b[i].x*v.z;
if( v.x > 0 )
nde[cnt].z = b[i].x;
else nde[cnt].z = -b[i].x;
nde[cnt++].id = 1;
}
sort( nde, nde+cnt, cmp );
k = nde[0].id;
// k = 1说明前面出现过弓箭手;
for( int i = 1; i < cnt; i++ ){
if( nde[i] == nde[i-1] ){
if( k && nde[i].id == 0 ) ans++; //前面有弓箭手并且位置相同
if( nde[i].id ) k = 1;
}
else k = nde[i].id; //位置不一样,重置k;
}
cout<<"Case "<<++t<<": ";
cout<<ans<<endl;
}
return 0;
}