宝岛地图(dp)

勇敢的水手们到达了一个小岛,在这个小岛上,曾经有海盗在这里埋下了一些宝藏。然而,我们的船快抛锚了,与此同时,船长发现藏宝图的一角被老鼠咬掉了一块。

 

藏宝图可以用一个n×m大小的矩形表示。矩形中的每一小块表示小岛中的一小块陆地(方块的边长为1米)。有一些方块表示的是海,这些块人是不能通过的。除了海不能走,其它的小方块都是可以行走的。在可行走区域里有一些小方块表示一些已知的地点。

 

另外,在地图上有k条指令。每条指令的格式表示如下:

“向y方向走n米”。

 

这里的方向有四种:“北”,“南”,“东”,“西”。如果你正确的跟着这些指令行走,并且完整的执行完所有指令,你就可以找到宝藏所在的地点。

 

但是,很不幸,由于地图中好多地方都缺失了,船长也不知道从哪些地方开始走。但是船长依然清楚地记得一些已知的地点。另外,船长也知道所有可行走区域。

 

现在船长想知道从哪些已知地点出发,按照指令,可能找到宝藏所在地。


Input
单组测试数据 
第一行包含两整数n和m(3≤n,m≤1000)。 
接下来的n行每行有m个字符,表示整个地图。 
“#”代表海。在地图矩形中,矩形的四周一圈一定是海。 
“.”代表可行走区域,未知地点。大写字母“A”到“Z”表示可行走区域,已知地点。 
所有大写字母不一定都被用到。每个字母在地图中最多出现一次。所有已知地点用不同的大写字母表示。 

接下来一行有一个整数k(1≤k≤10^5),接下来有k行。 
每行表示一条指令。 
指令格式为“dir len”,“dir”表示朝哪个方向走,“len”表示走几步。 
“dir”有四种取值“N”,“S”,“E”,“W”,对应题目中的“北”,“南”,“东”,“西” 
在地图中,北是在顶部,南是在底部,西是在左边,东是在右边。“len”是一个整数,范围在 11000 1,1000
Output
共一行,按字典序升序打印出所有可以完整执行地图中指令的已知区域的字母,如果没有满足要求的已知区域,则打印“no solution”(没有引号)。
Sample Input
输入样例1
6 10
##########
#K#..#####
#.#..##.##
#..L.#...#
###D###A.#
##########
4
N 2
S 1
E 1
W 2
Sample Output
输出样例1

AD

思路 :做两个二维数组dp # 的个数,检测每次水平或者竖直移动 len 之间是否隔海。当然也可以设置一个三维数组,作用相同。在读入地图时存取出现的大写字母及其初始坐标,对每个指令依次判断,如果不行则标记,最后输出。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;

typedef pair <int ,int> ii;

char mp[1100][1100];
int sea1[1100][1100];   // 列
int sea2[1100][1100];   // 行

map <char,ii > pos;
map <char,ii > dir;
map <char,int> mark;
char record[26];

int main(){
    int m,n;
    dir['N'].first = -1,dir['N'].second = 0;
    dir['S'].first = 1 ,dir['S'].second = 0;
    dir['E'].first = 0, dir['E'].second = 1;
    dir['W'].first = 0, dir['W'].second =-1;
    scanf("%d%d",&m,&n);
    getchar();
    int k = 0;
    for(int i = 1; i <=m; i++)
    {
        for(int j = 1; j <=n; j++)
        {
            scanf("%c",&mp[i][j]);
            if(mp[i][j] >= 'A' && mp[i][j] <= 'Z')
            {
                char c = mp[i][j];
                record[k++] = c;
                mark[c] = 1;
                pos[c].first = i;
                pos[c].second = j;
            }
            if(mp[i][j] == '#')
            {
                sea1[i][j] = sea1[i][j-1] + 1;
                sea2[i][j] = sea2[i-1][j] + 1;
            }
            else
            {
                sea1[i][j] = sea1[i][j-1] ;
                sea2[i][j] = sea2[i-1][j] ;
            }
        }
        getchar();
    }
    int q,x;
    char s[10];
    scanf("%d",&q);
    getchar();
    while(q--)
    {
        scanf("%s%d",s,&x);
        for(int j = 0; j < k; j++)
        {
            char c = record[j];
            if(!mark[c]) continue;
            int x_ = pos[c].first;
            int y_ = pos[c].second;
            int zx = x_ + dir[s[0]].first  *x;
            int zy = y_ + dir[s[0]].second *x;
            pos[c].first = zx;
            pos[c].second = zy;
            if(zx < 1 || zy < 1 || zx > m || zy > n)
            {
                mark[c] = 0;
                continue;
            }
            if(s[0] == 'S')
            {
                if(sea2[zx][zy] - sea2[x_-1][y_])
                {
                     mark[c] = 0;
                     continue;
                }
            }
            if(s[0] == 'E')
            {
                if(sea1[zx][zy] - sea1[x_][y_-1])
                {
                     mark[c] = 0;
                     continue;
                }
            }
            if(s[0] == 'N')
            {
                if(sea2[x_][y_]-sea2[zx-1][zy])
                {
                    mark[c] = 0;
                    continue;
                }
            }
            if(s[0] == 'W')
            {
                if(sea1[x_][y_]-sea1[zx][zy-1])
                {
                    mark[c] = 0;
                    continue;
                }
            }
         }
    }
    bool yes = 1;
    for(int i = 0; i < 26; i++)
    {
        char c = 'A' + i;
        if(mark[c])
        {
            yes = 0;
            printf("%c",c);
        }
    }
    if(yes) printf("no solution");
    printf("\n");
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值