题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 ,第一次写状压,感觉还可以。
状态表示的思想其实就是用一个数值将每一层的情况给表示出来,而状态压缩是用位运算来简化这种表示方法。
题解:
在当前的状态里添加一个key值,表示现在手上所拿的钥匙数,key值其实是一个二进制表示,001表示拿到了a钥匙,1011表示拿到了a、b、d这三把钥匙。当BFS遇到钥匙的时候,即可进行与运算将遇到的钥匙添加到key值中,当遇到门的时候,即进行或运算来判断当前的门的钥匙是否已经拿到。
这里要注意的是vis数组的表示方法,vis[v.x][v.y][v.key]代表在v.key的状态下(v.x , v.y)的访问情况,其余部分按照正常BFS即可。
#include <iostream> #include <cstdio> #include <vector> #include <queue> #include <stack> #include <cmath> #include <string> #include <string.h> #include <algorithm> using namespace std; int dir[4][2] = {0 , -1 , -1 , 0 , 0 , 1 , 1 , 0}; int vis[21][21][1030] , pow2[25]; char map[25][25]; int n , m , t; struct Point { int x , y , key , step; }; void init() { pow2[0] = 1; for(int i = 1 ; i <= 24 ; i++) pow2[i] = 1 << i; } bool place(int x , int y) { if(x < 0 || y < 0 || x >= n || y >= m || map[x][y] == ‘*‘) return false; return true; } int bfs(int sx , int sy) { queue <Point> que; Point tmp = {sx , sy , 0 , 0}; que.push(tmp); memset(vis , 0 , sizeof(vis)); vis[sx][sy][0] = 1; while(!que.empty()) { Point u = que.front(); que.pop(); for(int i = 0 ; i < 4 ; i++) { int tx = u.x + dir[i][0]; int ty = u.y + dir[i][1]; if(place(tx , ty) && !vis[tx][ty][u.key]) { if(map[tx][ty] == ‘^‘) return u.step + 1; Point v = {tx , ty , u.key , u.step}; if(map[tx][ty] >= ‘A‘ && map[tx][ty] <= ‘J‘) { int c = map[tx][ty] - ‘A‘; if(v.key & pow2[c]) { vis[tx][ty][v.key] = 1; v.step += 1; que.push(v); } } else if(map[tx][ty] >= ‘a‘ && map[tx][ty] <= ‘j‘) { int c = map[tx][ty] - ‘a‘; if(!vis[tx][ty][v.key | pow2[c]]) { v.key = v.key | pow2[c]; vis[tx][ty][v.key] = 1; v.step += 1; que.push(v); } } else if(map[tx][ty] == ‘.‘ || map[tx][ty] == ‘@‘) { vis[tx][ty][v.key] = 1; v.step += 1; que.push(v); } } } } return -1; } int main() { init(); while(~scanf("%d %d %d" , &n , &m , &t)) { for(int i = 0 ; i < n ; i++) scanf("%s" , map[i]); int x , y; for(int i = 0 ; i < n ; i++) { for(int j = 0 ; j < m ; j++) { if(map[i][j] == ‘@‘) { x = i; y = j; } } } int res = bfs(x , y); if(res == -1 || res >= t) puts("-1"); else printf("%d\n" , res); } return 0; }
时间: 2024-10-13 08:15:58