• 双向bfs, A*以及其他搜索算法


    总结

    例题

    1

    万圣节后的早晨

    普通bfs

    重点在代码里

    //以下关于编码解码的内容,以后再看,现在注重算法 
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int N = 20;
    const int MAXN = 200;// 75% cells plus 2 fake nodes
    const int mx[] = {-1, 1, 0, 0, 0};
    const int my[] = {0, 0, -1, 1, 0};//包括不移动 
    
    inline int ID(int a, int b, int c) {//编码 
    	return (a<<16)|(b<<8)|c;
    }
    
    int r, c, n;
    int s[3], t[3];//三只鬼的起点&终点
    
    int G[MAXN][6];
    //重点1 : G用来把空格重组成一张图,G[i][0]表示标号为i的空格周围能走的格子数//邻接表嘛 
    //G[i][1~5]表示下一步鬼从i可以走到的空格的编号 (其实也可以记录dir 
    
    inline int comflict(int a, int b, int a2, int b2) {
    //	return (a==a2&&b==b2) || (a==b2&&b==a2); 这是我傻了...这不是坐标!这是编号 
    	return a2 == b2 || (a2 == b && b2 == a);//判断同时移动的时候是否冲突 
    }
    
    int dis[MAXN][MAXN][MAXN];
    
    int bfs() {
    	queue<int> q;
    	memset(dis, -1, sizeof(dis));
    	q.push(ID(s[0], s[1], s[2]));
    	dis[s[0]][s[1]][s[2]] = 0;
    	while(!q.empty()) {
    		int u = q.front(); q.pop();
    		int a = (u>>16)&0xff, b = (u>>8)&0xff, c = u&0xff;//解码 
    		if(a==t[0] && b==t[1] && c==t[2]) return dis[a][b][c];
    		
    		for(int i = 1; i <= G[a][0]; i++) {
    			int a2 = G[a][i];
    			for(int j = 1; j <= G[b][0]; j++) {
    				int b2 = G[b][j];
    				if(comflict(a, b, a2, b2)) continue;
    				for(int k = 1; k <= G[c][0]; k++) {
    					int c2 = G[c][k];
    					if(comflict(a, c, a2, c2)) continue;
    					if(comflict(b, c, b2, c2)) continue;
    					if(dis[a2][b2][c2] != -1) continue;
              			dis[a2][b2][c2] = dis[a][b][c]+1;
                		q.push(ID(a2, b2, c2));
    				}
    			}
    		}
    	}
    	return -1;
    }
    
    int main() {
    	while(scanf("%d%d%d
    ", &c, &r, &n) == 3 && n) {//记得在这加上“
    ” 
    		char M[N][N];//以后这样的,不是全局变量的,只在main里面声明就行了,不用init了
    		for(int i = 0; i < r; i++) {
    			fgets(M[i], 20, stdin); 
    //			printf("	%d
    ", i);
    		}
    		//从原图中抽出空格,并确定初末位置
    		int cnt, x[MAXN], y[MAXN], id[MAXN][MAXN];//用id[][]来给G[][]赋值,这样会方便很多 
    		cnt = 0; //cnt:空格数(顺便编号
    		for(int i = 0; i < r; i++) 
    			for(int j = 0; j < c; j++) if(M[i][j] != '#') {
    				x[cnt] = i; y[cnt] = j; id[i][j] = cnt;
    				if(islower(M[i][j])) s[M[i][j] - 'a'] = cnt;
    				else if(isupper(M[i][j])) t[M[i][j] - 'A'] = cnt;
    				cnt++;
    			} 
    		
    		//用空格,邻接表建图: 即计算G 
    		for(int i = 0; i < cnt; i++) {
    			G[i][0] = 0;
    			for(int dir = 0; dir < 5; dir++) {
    				int x2 = x[i]+mx[dir], y2 = y[i]+my[dir];
    				if(M[x2][y2] != '#') G[i][++G[i][0]] = id[x2][y2];//由题意:没必要判越界 
    			}
    		} 
    		
    		//重点2: 添加fake节点,简化code
    		if(n <= 2) {G[cnt][0] = 1; G[cnt][1] = cnt; s[2] = t[2] = cnt; cnt++;}
    		if(n <= 1) {G[cnt][0] = 1; G[cnt][1] = cnt; s[1] = t[1] = cnt; cnt++;}
    		
    		printf("%d
    ", bfs()); 
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux时间设置相关
    tcp/ip协议和http协议
    redis和memcache的比较
    How to Display Image In Picturebox in VC++ from Iplimage and Mat
    关于技术与业务的理解
    怎样写出好代码——设计原则
    怎么写出好代码——坏味道
    linux 用户管理
    浅谈ajax
    浅析闭包和内存泄露的问题
  • 原文地址:https://www.cnblogs.com/tyner/p/12080218.html
Copyright © 2020-2023  润新知