注意:进入循环!=回到出发点,代码超时有可能是这个原因
【问题描述】
有一个 n×m 的网格,其中包含一些实心单元和一些空心单元。网格左上角的坐标为(1, 1),而右下角的坐标为(n, m)。其中有 k 个实心单元,而其他的则是空心的。这时从坐标为( xs,ys )的单元中心向四个对角方向之一(也就是东北、西北、东南和西南)的方向发射一个激光束,如果激光束遇到实心单元或网格边缘则形成反射或折射。方式如下(入射角度为NE为例):

一段时间后,激光束将进入一个死循环,计算在进入死循环之前激光束穿越至少一次的空单元格总数,穿越是指穿过单元中心。
【输入形式】
输入的第一行包含三个整数 n、m 和 k (1≤n、m≤1000, 0≤k≤1000)。接下来的 k 行每行包含两个整数 xi 和 yi (1≤xi≤n,1≤yi≤m),表示第 i 个实心单元的位置。
最后一行包含两个整数xs 、 ys (1≤xs≤n,1≤ys≤m)以及激光发射方向,分别用"NE"、"NW"、"SE"、"SW"代表东北、西北、东南、西南方向。
【输出形式】
输出仅有一行一个数字,表示激光束进入死循环之前所穿越过至少一次的空心单元格的总数。
【样例输入1】
3 3 0 1 2 SW
【样例输出1】
6
【样例输入2】
7 5 3 3 3 4 3 5 3 2 1 SE
【样例输出2】
14
【提示】
可以将 n×m 的网格扩大为(n+2)×(m+2),其中的所有:
(0, i), i=0,1,...,m+1单元
(j, 0),j=0,1, ..., n+1单元
(n+1, i), i=0,1,...,m+1单元
(j, m+1), j=0, 1,...,n+1单元
都可以看做为实心单元。
【评分标准】274E
代码如下
#include<bits/stdc++.h>
using namespace std;
//思路是最直观的模拟
int main()
{
char s[200][200];
int n,m,k,xs,ys;//1~n 0 n+1
char str;//qNW eNE zSW cSE
cin>>n>>m>>k;
//初始化
memset(s,'0',sizeof(s));
for(int i=0; i<=n+1; i++)
{
s[i][0]='1';
s[i][m+1]='1';
}
for(int i=0; i<=m+1; i++)
{
s[0][i]='1';
s[n+1][i]='1';
}
for(int i=0; i<k; i++)
{
int xi,yi;
cin>>xi>>yi;
s[xi][yi]='1';
}
string ss;
int sum=0;
cin>>xs>>ys>>ss;
if( ss=="SW" ) str='z';
else if( ss=="SE") str='c';
else if( ss=="NW") str='q';
else if( ss=="NE") str='e';
//xs,ys,str表示当前的坐标(索引)与指向
//模拟路径
while(1)
{
if( s[xs][ys]==str )
{
break;
}
else if( s[xs][ys]=='0' )
{
sum++;
s[xs][ys]=str;
}
if( str=='q' )
{
if(s[xs-1][ys-1]!='1') { xs--; ys--; }
else
{
if(s[xs][ys-1]=='1' && s[xs-1][ys]=='1'){str='c'; }
else if( s[xs-1][ys]=='1' ) { ys--; str='e'; }
else if( s[xs][ys-1]=='1' ) { xs--; str='z'; }
}
}
else if( str=='e' )
{
if(s[xs+1][ys-1]!='1') { xs++; ys--; }
else
{
if(s[xs+1][ys]=='1' && s[xs][ys-1]=='1'){ str='z'; }
else if( s[xs][ys-1]=='1' ) { xs++; str='c'; }
else if( s[xs+1][ys]=='1' ) { ys--; str='q'; }
}
}
else if( str=='z' )
{
if(s[xs-1][ys+1]!='1') { xs--; ys++; }
else
{
if(s[xs-1][ys]=='1' && s[xs][ys+1]=='1'){ str='e'; }
else if( s[xs][ys+1]=='1' ) { xs--; str='q'; }
else if( s[xs-1][ys]=='1' ) { ys++; str='c'; }
}
}
else if( str=='c' )
{
if(s[xs+1][ys+1]!='1') { xs++; ys++; }
else
{
if(s[xs][ys+1]=='1' && s[xs+1][ys]=='1'){ str='q'; }
else if( s[xs][ys+1]=='1' ) { xs++; str='e'; }
else if( s[xs+1][ys]=='1' ) { ys++; str='z'; }
}
}
}
cout<<sum;
return 0;
}
文章介绍了一种算法,用于计算激光束在包含实心单元和空心单元的网格中,从特定起点发射并可能形成反射直至进入死循环前穿越空心单元的数量。
1799

被折叠的 条评论
为什么被折叠?



