一.问题描述
二.问题分析及思路
一开始考虑用数组保存单元格,用一个函数模拟激光行进过程,遇到反射/折射情况就停止当前方向的行进,改变方向,重新调用函数,数组是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;
}