您的位置:首页 > 其它

玲珑杯 1143 - 计算几何你瞎暴力(暴力+YY)——“玲珑杯”ACM比赛 Round #18

2017-07-17 19:35 656 查看
1143 - 计算几何你瞎暴力

Time Limit:5s Memory Limit:256MByte

Submissions:1828Solved:365

DESCRIPTION

今天HHHH考完了期末考试,他在教学楼里闲逛,他看着教学楼里一间间的教室,于是开始思考:

如果从一个坐标为 (x1,y1,z1)(x1,y1,z1)的教室走到(x2,y2,z2)(x2,y2,z2)的距离为|x1−x2|+|y1−y2|+|z1−z2||x1−x2|+|y1−y2|+|z1−z2|

那么有多少对教室之间的距离是不超过RR的呢?

INPUT

第一行是一个整数T(1≤T≤10)T(1≤T≤10),
表示有TT组数据接下来是TT组数据,对于每组数据:第一行是两个整数n,q(1≤n≤5×104,1≤q≤103)n,q(1≤n≤5×104,1≤q≤103),
表示有nn间教室,qq次询问.接下来是nn行,
每行3个整数xi,yi,zi(0≤xi,yi,zi≤10)xi,yi,zi(0≤xi,yi,zi≤10),表示这间教室的坐标.最后是qq行,每行一个整数R(0≤R≤109)R(0≤R≤109),意思见描述.

OUTPUT

对于每个询问RR输出一行一个整数,表示有多少对教室满足题目所述的距离关系.

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: