【问题描述】
有一个 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
//注:此题数组下标从1开始而不是0,便于计数 - using namespace std;
- int main()
- {
- string direction;
- int n,m,k;
- int xs,ys;
- cin>>n>>m>>k;
- int Black[n+1][m+1];//记录黑色方块的位置
- int Cnt[n+1][m+1];//记录激光经过的方块
- int arr[k][2];
- fill(Black[0],Black[0]+(n+1)*(m+1),0);
- fill(Cnt[0],Cnt[0]+(n+1)*(m+1),0);//将Black和Cnt数组全部归零
- for(int i=1;i<=k;i++)
- {
- cin>>arr[i][0]>>arr[i][1];
- Black[arr[i][0]][arr[i][1]]++;
- }
- cin>>xs>>ys>>direction;
- Cnt[xs][ys]=1;//先标注起点
- int Startx=xs,Starty=ys;
- int flagx=Startx,flagy=Starty;
- string flagd=direction;
- while(1)
- {
- //一.--------------------------------------------------------------------
- if(direction=="NE")//先确定方向 //皆为单步操作
- {
- if(Startx>1&&Starty
//没到边缘 - {
- if(Black[Startx-1][Starty+1]==1)//斜对角是黑色
- {
- if((Black[Startx][Starty+1]==1&&Black[Startx-1][Starty]==1)||(Black[Startx][Starty+1]!=1&&Black[Startx-1][Starty]!=1))
- {
- direction=="SW";
- }
- else if(Black[Startx][Starty+1]==1&&Black[Startx-1][Starty]!=1)
- {
- direction=="NW";
- Startx--;
- Cnt[Startx][Starty]++;
- }
- else if(Black[Startx][Starty+1]!=1&&Black[Startx-1][Starty]==1)
- {
- direction=="SE";
- Starty++;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Black[Startx-1][Starty+1]!=1)//斜对角为白块
- {
- Startx--;
- Starty++;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Startx==1&&Starty
//碰到上边缘 - {
- direction="SE";
- Starty++;
- Cnt[Startx][Starty]++;
- }
- else if(Startx>1&&Starty==m)//碰到右边缘
- {
- direction="NW";
- Startx--;
- Cnt[Startx][Starty]++;
- }
- else if(Startx==1&&Starty==m)//碰到右上方拐角
- {
- direction="SW";
- }
- }
- //---------------------------------------------------------------------
- //二.--------------------------------------------------------------------
- else if(direction=="SE")//先确定方向 //皆为单步操作
- {
- if(Startx
//没到边缘 - {
- if(Black[Startx+1][Starty+1]==1)//斜对角是黑色
- {
- if((Black[Startx][Starty+1]==1&&Black[Startx+1][Starty]==1)||(Black[Startx][Starty+1]!=1&&Black[Startx+1][Starty]!=1))
- {
- direction=="NW";
- }
- else if(Black[Startx][Starty+1]==1&&Black[Startx+1][Starty]!=1)
- {
- direction=="SW";
- Startx++;
- Cnt[Startx][Starty]++;
- }
- else if(Black[Startx][Starty+1]!=1&&Black[Startx+1][Starty]==1)
- {
- direction=="NE";
- Starty++;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Black[Startx+1][Starty+1]!=1)//斜对角为白块
- {
- Startx++;
- Starty++;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Startx
//碰到右边缘 - {
- direction="SW";
- Startx++;
- Cnt[Startx][Starty]++;
- }
- else if(Startx==n&&Starty
//碰到下边缘 - {
- direction="NE";
- Starty++;
- Cnt[Startx][Starty]++;
- }
- else if(Startx==n&&Starty==m)//碰到右下方拐角
- {
- direction="NW";
- }
- }
- //---------------------------------------------------------------------
- //三.--------------------------------------------------------------------
- else if(direction=="NW")//先确定方向 //皆为单步操作
- {
- if(Startx>1&&Starty>1)//没到边缘
- {
- if(Black[Startx-1][Starty-1]==1)//斜对角是黑色
- {
- if((Black[Startx][Starty-1]==1&&Black[Startx-1][Starty]==1)||(Black[Startx][Starty-1]!=1&&Black[Startx-1][Starty]!=1))
- {
- direction=="SE";
- }
- else if(Black[Startx][Starty-1]==1&&Black[Startx-1][Starty]!=1)
- {
- direction=="NE";
- Startx--;
- Cnt[Startx][Starty]++;
- }
- else if(Black[Startx][Starty-1]!=1&&Black[Startx-1][Starty]==1)
- {
- direction=="SW";
- Starty--;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Black[Startx-1][Starty-1]!=1)//斜对角为白块
- {
- Startx--;
- Starty--;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Startx>1&&Starty==1)//碰到左边缘
- {
- direction="NE";
- Startx--;
- Cnt[Startx][Starty]++;
- }
- else if(Startx==1&&Starty>1)//碰到上边缘
- {
- direction="SW";
- Starty--;
- Cnt[Startx][Starty]++;
- }
- else if(Startx==1&&Starty==1)//碰到左上方拐角
- {
- direction="SE";
- }
- }
- //---------------------------------------------------------------------
- //四.--------------------------------------------------------------------
- else if(direction=="SW")//先确定方向 //皆为单步操作
- {
- if(Startx
1)//没到边缘 - {
- if(Black[Startx+1][Starty-1]==1)//斜对角是黑色
- {
- if((Black[Startx][Starty-1]==1&&Black[Startx+1][Starty]==1)||(Black[Startx][Starty-1]!=1&&Black[Startx+1][Starty]!=1))
- {
- direction=="NE";
- }
- else if(Black[Startx][Starty-1]==1&&Black[Startx+1][Starty]!=1)
- {
- direction=="SE";
- Startx++;
- Cnt[Startx][Starty]++;
- }
- else if(Black[Startx][Starty-1]!=1&&Black[Startx+1][Starty]==1)
- {
- direction=="NW";
- Starty--;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Black[Startx+1][Starty-1]!=1)//斜对角为白块
- {
- Startx++;
- Starty--;
- Cnt[Startx][Starty]++;
- }
- }
- else if(Startx==n&&Starty>1)//碰到下边缘
- {
- direction="NW";
- Starty--;
- Cnt[Startx][Starty]++;
- }
- else if(Startx
1)//碰到左边缘 - {
- direction="SE";
- Startx++;
- Cnt[Startx][Starty]++;
- }
- else if(Startx==n&&Starty==1)//碰到左下方拐角
- {
- direction="NE";
- }
- }
- //---------------------------------------------------------------------
- if(Startx==flagx&&Starty==flagy&&direction==flagd)
- {
- break;
- }
- }
- int sum=0;
- for(int i=1;i<=n;i++)
- {
- for(int j=1;j<=m;j++)
- {
- if(Cnt[i][j]>0)
- {
- sum++;
- }
- }
- }
- cout<
- system("pause");
- return 0;
- }