问题 J: 任性
时间限制: 2 Sec 内存限制: 128 MB题目描述
任性大佬最喜欢的游戏是斗地主,不过今天他想去尝试一下坦克大战,游戏中可以用自己的坦克发射一束激光来攻击敌人,激光能被镜子反射。
任性大佬现在想要计算出激光一共能杀死几个敌人。
注意:激光在杀死敌人后穿过敌人;激光在遇到自己的坦克时会直接穿过;激光可以选择水平或竖直发射。
输入
有多组输入输出
在第一行输入两整数n, m (1 ≤ n, m ≤ 1000)分别代表地图的行数和列数,下面的n行,描述地图各行。
. 表示空地
* 表示障碍物(光线不能穿过,光线打到障碍物上时传播结束)
T 任性大佬的坦克的初始位置
E 表示敌人
/ 表示按照 从左下到右上 安放的镜子
\ 表示按照 从左上到右下 安放的镜子
输出
一个整数代表最多可以杀死的敌人数量
样例输入
5 5 .*/E\ E*.*. E*TEE \.../ .*\EE
样例输出
4
分析:分别枚举上下左右四个方向,取能杀死敌人最多的一个方向即可。用vis[i][j][k]表示是否在k方向上经过点(i,j),避免陷入死循环。
用异或运算可以实现一定范围内的数的置换,减少if的判断。
#include<bits/stdc++.h> using namespace std; char a[1100][1100]; int n,m; const int dx[]= {-1,0,1,0}; const int dy[]= {0,1,0,-1}; int vis[1100][1100][4]; bool ok(int x,int y) { for(int i=0; i<4; ++i) if(vis[x][y][i])return false; return true; } int main() { //freopen("i.txt","r",stdin); while(scanf("%d%d",&m,&n)==2) { int xx,yy; for(int i=0; i<m; ++i) for(int j=0; j<n; ++j) { scanf(" %c",&a[i][j]); if(a[i][j]=='T') xx=i,yy=j; } int maxn=0; for(int i=0; i<4; ++i) { memset(vis,0,sizeof vis); int p=i; int x=xx,y=yy; int cnt=0; while(x>=0&&x<m&&y>=0&&y<n&&!vis[x][y][p]&&a[x][y]!='*') { if(a[x][y]=='E'&&ok(x,y)) ++cnt; else if(a[x][y]=='/') p^=1; else if(a[x][y]=='\\') p^=3; vis[x][y][p]=1; x+=dx[p],y+=dy[p]; } maxn=max(maxn,cnt); } printf("%d\n",maxn); } }