HNU程序设计-激光

一.问题描述

二.问题分析及思路

        一开始考虑用数组保存单元格,用一个函数模拟激光行进过程,遇到反射/折射情况就停止当前方向的行进,改变方向,重新调用函数,数组是1000*1000的,虽然测试样例没那么大,但还是直接溢出了。最后改用了字符串保存单元格,还是有两个没对,等有时间再看吧。以下是字符串保存单元格的做法:

1.用一维字符串保存单元格状态,为空则赋为‘0’,实心则赋‘1’,初始化时全部手动赋0,大小是n+2个字符串,每个字符串长度m+2(包括边界,把边界当成实心来考虑)。边界取‘1’。

2.结构体保存光的位置x,y和行进方向dx,dy,x是行,y是列

3.函数内,如果下一个移动到的格子为空,移动到下一个格子,且把当前点放进已访问过的点中。如果下一个移动到的格子实心,且他旁边两个格子都实心或都为空,则原路返回,改变方向。如果他旁边有一个格子实心一个格子为空,则反射,改变方向。

4.最后统计访问过多少个格子

 三.代码

#include<iostream>
#include<cstring>
#include<set>
using namespace std;
struct light
{
	int x,y,dx,dy;							//记录当前位置,经过方格数,前进方向
};													//行为x,列为y
set<pair<int,int> > visited;
void move(light &a,string blocks[])
{
	if(blocks[a.x+a.dx][a.y+a.dy]=='0')
	{
		a.x=a.x+a.dx;
		a.y=a.y+a.dy;
		pair<int,int> p(a.x,a.y);
		visited.insert(p);
	}
	else if(blocks[a.x+a.dx][a.y+a.dy]=='1'&&blocks[a.x][a.y+a.dy]==blocks[a.x+a.dx][a.y])
	{
		a.dx*=-1,a.dy*=-1;
	}
	else if(blocks[a.x][a.y+a.dy]=='1')
	{
		a.y+=a.dy;
		a.dy*=-1;
	}
	else
	{
		a.x+=a.dx;
		a.dx*=-1;
	}
	//cout<<a.x<<" "<<a.y<<" "<<a.dx<<" "<<a.dy<<endl;
	return;
}
int main()
{
	int n,m,k,t1,t2,startx,starty;
	cin>>n>>m>>k;
	string blocks[n+2];
	string direction;
	//初始化方格
	for(int i=0;i<n+2;i++)
	{
		for(int j=0;j<m+2;j++) blocks[i]+="0";
	}
	for(int i=0;i<m+2;i++) {blocks[0][i]='1';blocks[n+1][i]='1';}
	for(int i=0;i<n+2;i++) {blocks[i][0]='1';blocks[i][m+1]='1';}
	//数据输入
	for(int i=0;i<k;i++)
	{
		cin>>t1>>t2;
		blocks[t1][t2]='1';
	}
	cin>>startx>>starty>>direction;
	light a;
	a.x=startx,a.y=starty;
	if(direction[0]=='S') a.dx=1;
	else a.dx=-1;
	if(direction[1]=='E') a.dy=1;
	else a.dy=-1;
	do{
		move(a,blocks);
    }while(a.x!=startx||a.y!=starty);
    cout<<visited.size()<<endl;
    return 1;
}

Guess you like

Origin blog.csdn.net/Aaron503/article/details/121454189