【202206-4】光线追踪

这道题完成得十分艰难。
最初按照自己的想法只能得到运行超时的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;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值