这道题完成得十分艰难。
最初按照自己的想法只能得到运行超时的15分,后照着大佬的代码才勉强通过。
面向对象的思想实在有待加强。
以下是运行超时的15分:
思路是将镜面上的点存储,按照光线的路径走一步判断一下,如果该点是镜面点则变向等。
因数据量大起来后,走一步判断一步的方法效率太低,故15分运行超时。
#include<bits/stdc++.h>
using namespace std;
#define MAX 300005
map<int, map<int, int>>getID;
int K[MAX];
bool V[MAX];
double A[MAX];
int main()
{
int m, op, x1, y1, x2, y2, k, id;
int x, y, lowx, highx, lowy, highy, d, t;
double a, I;
scanf("%d", &m);
memset(K, sizeof(K), 0);
memset(V, sizeof(V), 0);
memset(A, sizeof(A), 0);
for (int i = 1; i <= m; ++i)
{
scanf("%d", &op);
if (op == 1)
{
scanf("%d %d %d %d %lf", &x1, &y1, &x2, &y2, &a);
k = (x1 - x2) / (y1 - y2);
lowx = x1 < x2 ? x1 : x2;
if (lowx == x1) { lowy = y1; highx = x2; highy = y2; }
else { lowy = y2; highx = x1; highy = y1; }
for (int j = lowx + 1; j < highx; ++j)
{
if (k == 1) lowy++;
else lowy--;
getID[j][lowy] = i;
A[i] = a; K[i] = k;
V[i] = true;
}
}
else if (op == 2)
{
scanf("%d", &id);
V[id] = false;
}
else if (op == 3)
{
scanf("%d %d %d %lf %d", &x, &y, &d, &I, &t);
for (int j = 1; j <= t; ++j)
{
if (I < 1.0)break;
if (d == 0) x++;
else if (d == 1) y++;
else if (d == 2) x--;
else if (d == 3) y--;
id = getID[x][y];
if (id > 0 && V[id] && j != t)
{
k = K[id];
if ((k == 1 && d == 0) || (k == -1 && d == 2))d = 1;
else if ((k == 1 && d == 1) || (k == -1 && d == 3))d = 0;
else if ((k == 1 && d == 2) || (k == -1 && d == 0))d = 3;
else if ((k == 1 && d == 3) || (k == -1 && d == 1))d = 2;
I = I * A[id];
}
}
id = getID[x][y];
if (id > 0 && V[id])I = I * A[id];
if (I < 1.0)cout << "0 0 0" << endl;
else cout << x << " " << y << " " << floor(I) << endl;
}
}
return 0;
}
参考了满分大佬的答案,来源此处。
以下是自己照着大佬的代码写copy 的……
思路不同于上一个的走一步看一步,而是直接查找到该方向第一个镜面点。
其中小到数据处理方式、数据结构、STL等,大到面向对象的编程思想都足够我好好学习领悟。
#include<bits/stdc++.h>
using namespace std;
struct mirror {
int x1, x2, y1, y2;
}mirror[100005];
map<int, map<int, int>> getID; //(x, y, id)
map<int, map<int, int>> psx, psy; //psx以y为索引、递增存储x与id
int K[100005]; // id -> 1/-1
double A[100005]; // id -> a
//使用枚举类型表示光线移动方向
enum LighterDir {
X_POS = 0,
Y_POS = 1,
X_NEG = 2,
Y_NEG = 3
};
int dx[] = { 1, 0, -1, 0 }, dy[] = { 0, 1, 0, -1 };
void add_point(int x, int y, int id)
{
auto it = psx.find(y);
if (it == psx.end()) {
map<int, int> add;
add.insert({ x, id }); psx.insert({ y, add });
}
else {
it->second.insert({ x, id });
}
it = psy.find(x);
if (it == psy.end()) {
map<int, int> add;
add.insert({ y, id }); psy.insert({ x, add });
}
else {
it->second.insert({ y, id });
}
}
int newDir(int k, int d) {
if ((k == 1 && d == 0) || (k == -1 && d == 2))return 1;
else if ((k == 1 && d == 1) || (k == -1 && d == 3))return 0;
else if ((k == 1 && d == 2) || (k == -1 && d == 0))return 3;
else if ((k == 1 && d == 3) || (k == -1 && d == 1))return 2;
return 0;
}
void reflect(int x, int y, int d, double I, int t)
{
int flag, x1, y1, id;
do {
flag = 0, x1 = x, y1 = y, id = 0;
if (d == X_POS || d == X_NEG) {
auto it = psx.find(y);
if (it == psx.end()) {
flag = 1; break;
}
map<int, int>::iterator it2;
if (d == X_POS) {
it2 = it -> second.upper_bound(x);
if (it2 == it -> second.end())
{ flag = 1; break; }
x1 = it2 -> first, id = it2->second;
}
else {
it2 = it -> second.lower_bound(x);
if (it2 == it -> second.begin()) {
flag = 1; break;
}
--it2;
x1 = it2 -> first, id = it2->second;
}
}else {
auto it = psy.find(x);
if (it == psy.end())
{ flag = 1;break; }
map<int, int>::iterator it2;
if (d == Y_POS) {
it2 = it -> second.upper_bound(y);
if (it2 == it -> second.end()) {
flag = 1;break;
}
y1 = it2->first, id = it2->second;
}
else {
it2 = it->second.lower_bound(y);
if (it2 == it->second.begin())
{ flag = 1;break; }
--it2;
y1 = it2->first, id = it2->second;
}
}
int dist = abs(x - x1) + abs(y - y1);
if(dist > t || I < 1.0){
x += dx[d] * t; y += dy[d] * t; break;
}
x = x1, y = y1; d = newDir(K[id], d);
I = I * A[id]; t = t - dist;
if (I < 1.0) break;
} while (t > 0);
if(flag == 1){
x += dx[d] * t; y += dy[d] * t;
}
int i = (int)I;
if (I < 1.0)//printf("0 0 0\n");
cout <<'0'<<' '<<'0'<<' '<<'0'<< endl;
else //printf("%d %d %.0f\n", x, y, I);
cout << x << ' ' << y << ' ' << i << endl;
return;
}
int main()
{
int m, op, x1, y1, x2, y2, k, id;
int x, y, lowx, highx, lowy, highy, d, t;
double a, I;
memset(K, sizeof(K), 0);
memset(A, sizeof(A), 0);
cin >> m;
for (int i = 1; i <= m; ++i)
{
cin >> op;
if (op == 1)
{
cin >> x1 >> y1 >> x2 >> y2 >> a;
mirror[i].x1 = x1, mirror[i].x2 = x2;
mirror[i].y1 = y1, mirror[i].y2 = y2;
k = (x1 - x2) / (y1 - y2);
lowx = x1 < x2 ? x1 : x2;
if (lowx == x1) { lowy = y1; highx = x2; highy = y2; }
else { lowy = y2; highx = x1; highy = y1; }
lowy = lowy + k;
for (int j = lowx + 1 ; j < highx; ++j, lowy = lowy + k)
{
getID[j][lowy] = i;
A[i] = a; K[i] = k;
add_point(j, lowy, i);
}
}
else if (op == 2)
{
scanf("%d", &id);
x1 = mirror[id].x1, x2 = mirror[id].x2;
y1 = mirror[id].y1, y2 = mirror[id].y2;
lowx = x1 < x2 ? x1 : x2;
if (lowx == x1) { lowy = y1; highx = x2; highy = y2; }
else { lowy = y2; highx = x1; highy = y1; }
k = K[id];
lowy = lowy + k;
for (int j = lowx + 1; j < highx; ++j, lowy = lowy + k)
{
psx[lowy].erase(j); psy[j].erase(lowy);
}
}
else if (op == 3)
{
cin >> x >> y >> d >> I >> t;
reflect(x, y, d, I, t);
}
}
return 0;
}