1143 - 计算几何你瞎暴力
Time Limit:5s Memory Limit:256MByte
Submissions:1828Solved:365
DESCRIPTION
今天HH考完了期末考试,他在教学楼里闲逛,他看着教学楼里一间间的教室,于是开始思考:
如果从一个坐标为 (x1,y1,z1)的教室走到(x2,y2,z2)的距离为|x1−x2|+|y1−y2|+|z1−z2|
那么有多少对教室之间的距离是不超过R的呢?
INPUT
第一行是一个整数
T(1≤T≤10), 表示有
T组数据接下来是
T组数据,对于每组数据:第一行是两个整数
n,q(1≤n≤5×104,1≤q≤103), 表示有
n间教室,
q次询问.接下来是
n行, 每行3个整数
xi,yi,zi(0≤xi,yi,zi≤10),表示这间教室的坐标.最后是
q行,每行一个整数
R(0≤R≤109),意思见描述.
OUTPUT
对于每个询问
R输出一行一个整数,表示有多少对教室满足题目所述的距离关系.
SAMPLE INPUT
13 30 0 01 1 11 1 1123
SAMPLE OUTPUT
113
HINT
对于样例,1号教室和2号教室之间的距离为3, 1号和3号之间的距离为3, 2号和3号之间的距离为0
解题思路:
观察每个点的坐标范围[0,10], 那么最多就会有 11*11*11个点,在观察每次询问的距离 R,R 最多只有 0-30,如果R < 30 ,那么最终的结果就是 C(n,2), 然后去去重,预处理 0-30 的结果,最好暴力找一下就行了。
代码:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include <string.h>
using namespace std;
typedef long long LL;
const int MAXN = 5e4+5;
struct Point{
int x, y, z;
}p[MAXN], pp[1200];
LL num[15][15][15];
LL dis(Point a, Point b){
return (LL)abs(a.x-b.x)+(LL)abs(a.y-b.y)+(LL)abs(a.z-b.z);
}
int cmp(Point a, Point b){
if(a.x == b.x){
if(a.y == b.y) return a.z < b.z;
return a.y < b.y;
}
return a.x < b.x;
}
LL t[35];
int Scan_Int()///输入外挂
{
int res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
int main()
{
int T;
T = Scan_Int();
while(T--){
memset(num, 0, sizeof(num));
int n, q;
scanf("%d%d", &n, &q);
LL ret = (LL)n*(LL)(n-1)/2;
for(int i=0; i<n; i++) {
scanf("%d%d%d",&p[i].x, &p[i].y, &p[i].z);
num[p[i].x][p[i].y][p[i].z]++;
}
LL ans = 0;
for(int i=0; i<=10; i++)
for(int j=0; j<=10; j++)
for(int k=0; k<=10; k++)
if(num[i][j][k] > 1)
ans += (num[i][j][k]*(num[i][j][k]-1)/2);
sort(p, p+n, cmp);
int cnt = 0;
pp[cnt++] = p[0];
for(int i=1; i<n; i++) if(p[i].x!=p[i-1].x || p[i].y!=p[i-1].y || p[i].z!=p[i-1].z) pp[cnt++] = p[i];
memset(t, 0, sizeof(t));
t[0] = ans;
for(int k=1; k<30; k++){
LL sum = ans;
for(int i=0; i<cnt; i++)
for(int j=i+1; j<cnt; j++)
if(dis(pp[i], pp[j]) <= (LL)k)
sum = sum + num[pp[i].x][pp[i].y][pp[i].z] * num[pp[j].x][pp[j].y][pp[j].z];
t[k] = sum;
}
while(q--){
int r; scanf("%d", &r);
///r = Scan_Int();
if(r >= 30) { printf("%lld\n",ret); continue; }
printf("%lld\n",t[r]);
}
}
return 0;
}