hrbust/哈理工oj 2110 Keys【dfs+巧妙的二维判重】
来源:互联网 发布:在职研究生英语软件 编辑:程序博客网 时间:2024/06/04 23:19
John is on a mission to steal some documents of importance from a one-story building. He has managed to get hold of a detailed floor plan of the building, indicating the locations of all the documents. There are doors in the building that require a key to be opened. John has some keys in his possession, and there are some keys in the building itself. Can you help him figure out how many documents he can steal?
InputOn the first line one positive number: the number of test cases, at most 100.
After that per test case:
# one line with two space-separated integers h and w (2 <= h; w <= 100): the height and width of the map.
# h lines with w characters describing the building:
## ’.’ is an empty space.
## ’*’ is an impenetrable wall.
## ’$’ is a document that John would like to steal.
## an uppercase letter is a door.
## a lowercase letter is a key that opens all doors corresponding to its uppercase equivalent.
# one line with a string consisting of distinct lowercase letters: the keys that John has in his possession. If he has no keys, the line contains “0” instead.
John can freely move around the outside of the building. For any given door, the number of available keys that open it can be zero, one, or more than one. For any given key, the number of doors that it opens can be zero, one or more than one. Keys can be reused.
Per test case:
# one line with an integer: the total number of documents that John can steal.
Sample Input3
5 17
*****************
.............**$*
*B*A*P*C**X*Y*.X.
*y*x*a*p**$*$**$*
*****************
cz
5 11
*.*********
*...*...*x*
*X*.*.*.*.*
*$*...*...*
***********
0
7 7
*ABCDE*
X.....F
W.$$$.G
V.$$$.H
U.$$$.J
T.....K
*SQPML*
irony
Sample Output
3
1
0
题目大意:给你一个n*m的图四个边缘的点可以当做入口,最初有一些钥匙,对应小写字母是指钥匙,对应大写字母是门,e.g:x钥匙能够开X的门。
思路:
对于入口的处理,最开始的思路是对这些出口放在一个结构体里边存上,当走到入口的时候,可以通向另外的入口。但是写了一发,TLE了,毕竟100*100的图的时候入口还是蛮多的,所以每一次走到入口处都遍历其他入口很耗时,所以这种思路是AC不掉的,后来从学长那里问到了正确思路,其实很简单,比如样例1,我们将图改变成这样就能简单解决了这个问题:
...................*****************...............**$*..*B*A*P*C**X*Y*.X...*y*x*a*p**$*$**$*..*****************....................
这样既能解决起点不确定的问题,还能解决超时的问题、
然后说判重问题,如果我们用状压来写,100*100*2^26的数组是开不出来的,所以状压+bfs的思路可以pass掉了,我们可以用vis【】【】数组+dfs来解决这个问题,如果遇到了新的钥匙,加入钥匙的同时,加上memet(vis);的操作就可以完美解决了这个问题、因为在没有拿到新钥匙之前,再重复走一个点是没有意义的,但是如果拿到了新钥匙,那么就有重复走一个点的必要,当然这个时候也要让output($)重新变成0,避免重复拿取的情况。
关键的问题都解决了,后边就是要仔细的写代码了。
#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>using namespace std;char aa[105][105];char a[105][105];//加了一圈.之后的图int n,m;int vis[105][105];//二维判重int fx[4]={0,0,1,-1};int fy[4]={1,-1,0,0};int key[105];//钥匙数组,数据1表示有这个钥匙,0表示没有int output;int check(int x ,int y)//判断走到的地方是否符合条件{ if(x>=0 &&x<=n+1 &&y>=0 &&y<=m+1 &&vis[x][y] == 0 ) return 1; return 0;}void dfs(int x,int y){ if(a[x][y]=='*')return ; vis[x][y]=1; if(isupper(a[x][y]))//如果遇到了门 { if(key[a[x][y]-'A']==0)return ;//没有对应的钥匙要return else//如果有钥匙就继续向下走 { for(int i=0;i<4;i++) { if(check(x+fx[i],y+fy[i])) { dfs(x+fx[i],y+fy[i]); } } } } if(a[x][y]=='$')//遇到钱和.都是一样的,只是遇到了钱output计数器要加一 { output++; for(int i=0;i<4;i++) { if(check(x+fx[i],y+fy[i])) { dfs(x+fx[i],y+fy[i]); } } } if(a[x][y]=='.') { for(int i=0;i<4;i++) { if(check(x+fx[i],y+fy[i])) { dfs(x+fx[i],y+fy[i]); } } } if(islower(a[x][y]))//如果遇到了钥匙 { if(key[a[x][y]-'a']!=0)//如果有这把钥匙就忽略掉继续走 { for(int i=0;i<4;i++) { if(check(x+fx[i],y+fy[i])) { dfs(x+fx[i],y+fy[i]); } } } else//否则要对vis清零,并且也要对计数器清零. { output=0; key[a[x][y]-'a']++; memset(vis,0,sizeof(vis)); for(int i=0;i<4;i++) { if(check(x+fx[i],y+fy[i])) { dfs(x+fx[i],y+fy[i]); } } } }}int main(){ int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(aa,'.',sizeof(aa)); memset(key,0,sizeof(key)); memset(vis,0,sizeof(vis)); memset(a,'.',sizeof(a)); for(int i=0;i<n;i++) { scanf("%s",aa[i]); } for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { a[i+1][j+1]=aa[i][j]; } } char tmp[50]; scanf("%s",tmp); if(tmp[0]!='0') { for(int j=0;j<strlen(tmp);j++)key[tmp[j]-'a']++; } output=0; dfs(0,0); printf("%d\n",output); }}
- hrbust/哈理工oj 2110 Keys【dfs+巧妙的二维判重】
- hrbust 哈理工oj 2179 组合【基础dfs过】
- hrbust 哈理工oj 1743 Word Search【DFS过】
- hrbust 2115,哈理工oj 2115 Equal【dfs+剪枝】
- hrbust 2046 哈理工oj 2046 最后的题目八个字【二维树状数组】
- hrbust 1954 哈理工oj 1954 神奇的国家【图论+邻接表+dfs】
- hrbust 1326 哈理工oj 1326 Leyni的国家【DFS+邻接表建图】
- Hrbust oj/哈理工 oj 1216数的划分
- 哈理工oj hrbust 2267 从前的运算符【思维】
- hrbust 1216/哈理工oj 1216 数的划分【dp】
- hrbust 1625 哈理工oj ikki的数字【树状数组】
- hrbust/哈理工oj 1475国王的宴会【树型dp】
- hrbust 2132 哈理工oj 2132 数方格【二维树状数组】
- hrbust/哈理工oj 1740 A Story on a Sunshine Beach【二维01背包+输出路径】
- hrbust 1687/哈理工oj 1687 买房子【二维最短路+SPFA】
- hrbust 哈理工oj 1588 神医【贪心】
- hrbust 哈理工oj 网线【MST+Prim】
- 哈理工oj/hrbust 1790 武林【DP】
- mybaits异常:org.apache.ibatis.binding.BindingException: Parameter 'date' not found.
- linux jdk 配置
- BeagleBone学习之——PWM
- 1.oracle的dump理解一 BH buffer header
- 配置Mysql数据库支持远程连接等操作的步骤
- hrbust/哈理工oj 2110 Keys【dfs+巧妙的二维判重】
- 广播--android学习
- css 网站布局
- 三种基本排序
- HDU 4301 Divide Chocolate(打表+dp)
- Ajax理解
- Android数据库SQLite
- 令牌桶算法限流
- 生成具有最少节点、高度为H的AVL树的程序