2018ACM校赛 J 任性

问题 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);
    }
}
 
 
 

猜你喜欢

转载自www.cnblogs.com/ncc62497/p/8947603.html