字符串 13.激光镜像

【问题描述】

      有一个 n×m 的网格,其中包含一些实心单元和一些空心单元。网格左上角的坐标为(1, 1),而右下角的坐标为(nm)。其中有 个实心单元,而其他的则是空心的。这时从坐标为( xsys )的单元中心向四个对角方向之一(也就是东北、西北、东南和西南)的方向发射一个激光束,如果激光束遇到实心单元或网格边缘则形成反射或折射。方式如下(入射角度为NE为例):

       一段时间后,激光束将进入一个死循环,计算在进入死循环之前激光束穿越至少一次的空单元格总数,穿越是指穿过单元中心。

 

【输入形式】

       输入的第一行包含三个整数 n和 (1≤nm≤1000, 0≤k≤1000)。接下来的 k 行每行包含两个整数 xi 和 yi (1≤xin,1≤yim),表示第 i 个实心单元的位置。

       最后一行包含两个整数xs 、 ys (1≤xsn,1≤ysm)以及激光发射方向,分别用"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>//注:此题数组下标从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<m)//没到边缘
		{
			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<m)//碰到上边缘 
		{
			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<n&&Starty<m)//没到边缘
		{
			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<n&&Starty==m)//碰到右边缘 
		{
			direction="SW";
			Startx++;
			Cnt[Startx][Starty]++;
		}
		else if(Startx==n&&Starty<m)//碰到下边缘 
		{
			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<n&&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=="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<n&&Starty==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<<sum<<endl;
	system("pause");
	return 0;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一二爱上蜜桃猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值