QDUOJ 东北大炸弹 宝岛地图-枚举+数组记录+前缀和
冰清玉洁丶YCB
发布时间: 2017年6月18日 21:39 最后更新: 2017年6月18日 21:40 时间限制: 1000ms 内存限制: 256M
YCB是公认的冰清玉洁,人称锦州刚猛好男儿,凌河区一把刀。
一天YCB来到了一个n × m迷宫,每一个单位或者是空地("."),或者是墙("*")。
YCB当时就不乐意了,毕竟做为锦州刚猛好男儿,怎能被区区几个墙给挡住?
于是YCB选择在一个单位放置一个东北大炸弹(如果炸弹在(x, y),那么第x行和第y列的墙都会被炸掉),而且这个炸弹可以放在任何一个单位,无论是空地(".")还是墙("*")。
但是YCB已经被愤怒冲昏了头脑,失去了最宝贵的智力。
现在YCB想知道,是否存在一个点,将东北大炸弹放在这之后,能使得迷宫里面所有的单位都为空地。
聪明的你快来帮帮YCB吧,相信你一定做不出来。
单组输入
第一行是n 和 m (1 ≤ n, m ≤ 1000) — 迷宫的行数和列数。
接下来n行m列的迷宫。"."表示空地, "*"表示墙。
输出是否存在一个点,使得将东北大炸弹放置在这,能使得迷宫里面所有的单位都为空地。
如果有,输出"YES",否则输出"NO"。
3 4 .*.. .... .*..
YES
3 3 ..* .*. *..
NO
6 5 ..*.. ..*.. ***** ..*.. ..*.. ..*..
YES
宝岛地图
勇敢的水手们到达了一个小岛,在这个小岛上,曾经有海盗在这里埋下了一些宝藏。然而,我们的船快抛锚了,与此同时,船长发现藏宝图的一角被老鼠咬掉了一块。
藏宝图可以用一个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”是一个整数,范围在1,10001,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
两道题均可用暴力枚举完成,但会超时。我们可以利用数组记录来减少枚举,思想是空间换时间。东北大炸弹可以用数组把每行每列的障碍物个数记录下来,当访问到这一点时,不用再枚举行列,直接对行列数组值求和即可;宝岛地图是学长的题,也是利用数组记录,把可走点记为1,不可走点记为0,行列连续点值分别相加,记录区间可走点个数,前缀和,当步数+1(区间)=区间可走点个数,则可以走通。相当于给定爆炸范围的东北大炸弹。
1题:行列障碍个数 2题:行列区间可走点个数
#include<stdio.h> #include<string.h> int main() { char c; int a[1005][1005],h[1005],l[1005]; int n,m,co1,co2,i,j,k; scanf("%d%d",&n,&m); getchar(); memset(a,0,sizeof(a)); memset(h,0,sizeof(h)); memset(l,0,sizeof(l)); co1=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ scanf("%c",&c); if(c=='*'){ a[i][j]=1; co1++; h[i]++; l[j]++; } } getchar(); } if(co1==0) printf("YES\n"); else { int f=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ co2=0; co2+=h[i]; co2+=l[j]; if((a[i][j]&&co1==co2-1)||(!a[i][j]&&co1==co2)){ printf("YES\n"); f=1; break; } } if(f) break; } if(!f) printf("NO\n"); } return 0; }
#include<stdio.h> char a[1005][1005]; char c[100005]; int d[100005]; int hh[1005][1005],ll[1005][1005]; int re[26]; int main() { int n,m,k,x,y,i,j,l,l2; scanf("%d%d",&n,&m); for(i=0;i<n;i++){ getchar(); scanf("%s",a[i]); } for(i=0;i<n;i++){ for(j=0;j<m;j++){ hh[i][j]=hh[i][j-1]; if(a[i][j]!='#') hh[i][j]++; } } for(j=0;j<m;j++){ for(i=0;i<n;i++){ ll[i][j]=ll[i-1][j]; if(a[i][j]!='#') ll[i][j]++; } } scanf("%d",&k); for(i=1;i<=k;i++){ getchar(); scanf("%c%d",&c[i],&d[i]); } for(i=0;i<n;i++){ for(j=0;j<m;j++){ if('A'<=a[i][j]&&a[i][j]<='Z'){ x=i;y=j; for(l=1;l<=k;l++){ if(c[l]=='N'){ if(d[l]+1!=ll[x][y]-ll[x-d[l]-1][y]) break; x-=d[l]; } else if(c[l]=='S'){ if(d[l]+1!=ll[x+d[l]][y]-ll[x-1][y]) break; x+=d[l]; } else if(c[l]=='E'){ if(d[l]+1!=hh[x][y+d[l]]-hh[x][y-1]) break; y+=d[l]; } else if(c[l]=='W'){ if(d[l]+1!=hh[x][y]-hh[x][y-d[l]-1]) break; y-=d[l]; } if(l==k) re[a[i][j]-'A']=1; } } } } int f=0; for(i=0;i<26;i++){ if(re[i]==1){ printf("%c",i+'A'); f=1; } if(i==25&&f==0) printf("no solution"); } printf("\n"); return 0; }