# bzoj1094: [ZJOI2007]粒子运动

3 篇文章 0 订阅
10 篇文章 0 订阅

计算几何

## 【注意】

WA了两次，第一次是法向量求错，第二次是因为一个奇葩的思路，并没有求所有点任意时刻的最短距离（我简直脑。。残。。）。这题竟然写了5个多小时

## 【参考资料】

1、某神的博客1

2、某神的博客2

double solve(int i,int j)
{
//......
while(p<k||q<k)//应该同时满足
//......
}

0 0 10000
2 50
1948.000 1642.000 406.000 925.000
4203.000 5406.000 351.000 212.000

（2）程序输出为7.670，而正确结果应该是163.253

## 【代码】

/**************************************************************
Problem: 1094
User: zhengly123
Language: C++
Result: Accepted
Time:176 ms
Memory:2848 kb
****************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <algorithm>
#include <string.h>
#define MEM(a) memset(a,0,sizeof(a))
#define CPY(a,b) memcpy(b,a,sizeof(b))
using namespace std;
const int INF = 999999999;
const double INFdb = 1e200;
const int MAXN = 200;
const double eps = 1e-8;

inline double MIN(double a, double b){ return (a < b) ? a : b; }

inline double MAX(double a, double b){ return (a > b) ? a : b; }

int zero(double a)
{
if (fabs(a) < eps) return 0;
else return (a>0) ? 1 : -1;
}

struct point
{
double x, y;
point(){}
point(double a, double b){ x = a; y = b; }
friend point operator+(const point&a, const point&b){ return point(a.x + b.x, a.y + b.y); }
friend point operator -(const point&a, const point&b){ return point(a.x - b.x, a.y - b.y); }
friend point operator *(const double&k, const point&a){ return point(k*a.x, k*a.y); }//数乘
friend point operator /(const point&a, const double&b){ return point(a.x / b, a.y / b); }
friend double operator *(const point&a, const point&b){ return a.x*b.x + a.y*b.y; }//点积
friend double operator /(const point&a, const point&b){ return a.x*b.y - a.y*b.x; }//叉积,用^优先级有问题
friend bool operator <(const point&a, const point&b){ return (a.x - b.x < -eps) || (fabs(a.x - b.x) < eps && (a.y - b.y) < -eps); }
friend bool operator ==(const point&a, const point&b){ return zero(a.x - b.x) && zero(a.y - b.y); }
double dis(){ return (sqrt(x*x + y*y)); }
double spr(){ return(x*x + y*y); }
void input(){ scanf("%lf%lf", &x, &y); }
void output(){ printf("%lf %lf\n", x, y); }
}p[MAXN][MAXN], v[MAXN][MAXN], cir;

int num[MAXN], n, k;
double st[MAXN][MAXN], cx, cy, r;

void calc(int c,int k)//计算碰撞时间
{
point t = p[k][c] - cir;
double detla = 4 * (t*v[k][c])*(t*v[k][c]) - 4 * (v[k][c] * v[k][c])*(t*t - r*r);
if (zero(detla) == 0) detla = 0;
st[k + 1][c] = st[k][c] + (-2 * t*v[k][c] + sqrt(detla)) / (2 * v[k][c] * v[k][c]);
}

double cal(int c1, int c2, int k1, int k2, double strt, double endt)//计算最小距离
{
double ans, a, b, c, t;
point p1 = p[k1][c1] - p[k2][c2] - st[k1][c1] * v[k1][c1] + st[k2][c2] * v[k2][c2], p2 = v[k1][c1] - v[k2][c2];
a = p2*p2;
b = 2 * p1*p2;
c = p1*p1;
if (zero(a)==0)
{
if (b > 0) ans = strt;
else ans = endt;
return sqrt(b*ans + c);
}
else
{
t = -b / (2 * a);
if (t <= strt || zero(strt - t) == 0) ans = strt;
else if (t >= endt || zero(endt - t) == 0) ans = endt;
else ans = t;
return sqrt(a*ans*ans + b*ans + c);
}
}

void work()
{
int i, j, n, k1, k2;
double minn, ans = INFdb, t;
point ps, pi, pp;
cir.input();
scanf("%lf%d%d", &r, &n, &k);
for (i = 1; i <= n; ++i)
{
p[0][i].input();
v[0][i].input();
}
for (i = 1; i <= n; ++i)
{
for (j = 0; j < k; ++j)
{
calc(i, j);
t = st[j + 1][i] - st[j][i];//转折前时间
p[j + 1][i] = p[j][i] + t*v[j][i];//转折点
pp = p[j + 1][i] - cir;//对称轴
pi = point(-pp.y, pp.x);//法向量
v[j + 1][i] = (2 * (v[j][i] * pi / (pi*pi))) *pi - v[j][i];
++num[i];
}
}
for (i = 1; i <= n; ++i) for (j = i + 1; j <= n; ++j)
{
k1 = k2 = 0;
while (k1 < k&&k2 < k)
{
ans = MIN(ans, cal(i, j, k1, k2, MAX(st[k1][i], st[k2][j]), MIN(st[k1 + 1][i], st[k2 + 1][j])));
if (st[k1 + 1][i] < st[k2 + 1][j]) ++k1;
else ++k2;
}
}
printf("%.3lf\n", ans);
}

int main()
{
work();
return 0;
}

• 0
点赞
• 0
收藏
• 打赏
• 0
评论
11-08
09-04 82
04-10 1531
01-11 112
03-03 1094
02-21 285
01-30 53
05-05 3239
08-26 1053
01-02 49
05-02 53
04-12 719
03-04 1092

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

zhengly123

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。