kuangbin 数学训练一 Billiard Balls
题目链接:传送门#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define ll long longusing namespace std;const int N = 200010;struct Node {ll x, y;} nodes[N];//排序函
·
题目链接:
传送门
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 200010;
struct Node {
ll x, y;
} nodes[N];
//排序函数,x升序,y升序。
bool cmp(Node a, Node b) {
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
//w与l的含义与原题意思相反,因为我一开始l和w弄反了所以最后我改了输入,没改变量名
ll t, l, w, n, ca, k;
string op;
//向左移动
void moveToLeft(ll &x, ll k) {
k %= (2 * w);
if(k <= x) x -= k;
else if(k <= x + w) x = k - x;
else x = 2 * w - k + x;
}
//向右移动
void moveToRight(ll &x, ll k) {
k %= (2 * w);
if(x + k <= w) x += k;
else if(k < 2 * w - x) x = 2 * w - k - x;
else x = k + x - 2 * w;
}
//向上移动
void moveToTop(ll &y, ll k) {
k %= (2 * l);
if(y + k <= l) y += k;
else if(k < 2 * l - y) y = 2 * l - k - y;
else y = k + y - 2 * l;
}
//向下移动
void moveToBottom(ll &y, ll k) {
k %= (2 * l);
if(k <= y) y -= k;
else if(k <= l + y) y = k - y;
else y = 2 * l - k + y;
}
int main() {
scanf("%lld", &t);
while(t--) {
//初始化并输入数据
memset(nodes, 0, sizeof nodes);
scanf("%lld%lld%lld%lld", &w, &l, &n, &k);
for(int i = 1; i <= n; i++) {
scanf("%lld%lld", &nodes[i].x, &nodes[i].y);
cin >> op;
//判断应该走的方向
if(op == "NE") {
moveToTop(nodes[i].y, k);
moveToRight(nodes[i].x, k);
} else if(op == "SE") {
moveToBottom(nodes[i].y, k);
moveToRight(nodes[i].x, k);
} else if(op == "SW") {
moveToBottom(nodes[i].y, k);
moveToLeft(nodes[i].x, k);
} else {
moveToTop(nodes[i].y, k);
moveToLeft(nodes[i].x, k);
}
}
//排序
sort(nodes + 1, nodes + n + 1, cmp);
//输出
printf("Case %lld:\n", ++ca);
for(int i = 1; i <= n; i++) {
printf("%lld %lld\n", nodes[i].x, nodes[i].y);
}
}
}
这道题比较精妙的地方在于两个地方:
1.球与球之间的碰撞是可以忽视的,其实我们观察图即可发现碰撞以后其实相当于球与球之间进行了一个互换,总体的轨道其实并没有发生变化,所以球与球之间的碰撞可以忽视。我们只要关注触碰边界的反弹即可
2.x和y的计算其实是相对独立的我们可以分开来计算x和y的坐标,即计算上下移动后的y坐标和左右移动后的x坐标组合起来就是答案。
接下来分别讨论上下左右运动的情况,然后每种情况有三种情况要讨论,即第一次碰边界前,第一次碰边界后(第二次碰边界前),第二次碰边界后。由于如果运动时间大于l和w的话相当与来回运动了一次,所以计算时我们可以把这些没必要的来回通过求余去掉。
最后把答案排个序输出即可。
更多推荐
所有评论(0)