题目链接:传送门
题目大意:给你一个图,要从起点走到终点并且要吃够足够的金币才能出去,图上有金币(只能吃一次),
有传送门(用一次消耗1金币,必须有金币才能使用),问最少需要多少步才能出去。不能出去输出-1
题目思路:搜索+状态压缩技巧
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cstring> 7 #include <stack> 8 #include <cctype> 9 #include <queue> 10 #include <string> 11 #include <vector> 12 #include <set> 13 #include <map> 14 #include <climits> 15 #define lson root<<1,l,mid 16 #define rson root<<1|1,mid+1,r 17 #define fi first 18 #define se second 19 #define ping(x,y) ((x-y)*(x-y)) 20 #define mst(x,y) memset(x,y,sizeof(x)) 21 #define mcp(x,y) memcpy(x,y,sizeof(y)) 22 using namespace std; 23 #define gamma 0.5772156649015328606065120 24 #define MOD 1000000007 25 #define inf 0x3f3f3f3f 26 #define N 1000010 27 #define maxn 400005 28 typedef pair<int,int> PII; 29 30 int n,m,k,tx,ty; ///tx ty 记录终点位置 31 char pic[15][15]; 32 int vis[15][15][1<<5|1][6]; ///1,2维表示位置,第3维代表走到当前位置吃了哪些金币 33 int dir[][2]={{1,0},{-1,0},{0,1},{0,-1}}; ///第4维代表当前有多少金币 34 int dx[10],dy[10],dcnt; ///dcnt记录有多少传送门,前两个数组记录位置 35 struct Node{ 36 int x,y,v,cnt,fg; ///fg状态压缩表示当前吃了哪些金币 37 void ini(){ ///v代表当前有多少金币,cnt代表走了几步 38 v=cnt=fg=0; 39 } 40 }node,temp; 41 void bfs(){ 42 queue<Node>q; 43 q.push(node); 44 while(!q.empty()){ 45 node=q.front();q.pop(); 46 int x=node.x;int y=node.y; 47 if(x==tx&&y==ty){ 48 if(node.v>=k){ 49 printf("%d ",node.cnt); 50 return; 51 } 52 continue; 53 } 54 temp=node; 55 if(pic[x][y]=='P'&&temp.v){ ///走到了有传送门的位置 56 temp.cnt++; ///并且有路费可以用传送门 57 temp.v--; 58 for(int i=0;i<dcnt;++i){ 59 if((dx[i]==x&&dy[i]==y))continue; 60 int xx=dx[i],yy=dy[i]; 61 if(vis[xx][yy][temp.fg][temp.v])continue; 62 vis[xx][yy][temp.fg][temp.v]=1; 63 temp.x=xx;temp.y=yy; 64 q.push(temp); 65 } 66 } 67 for(int i=0;i<4;++i){ 68 temp=node; 69 temp.cnt++; 70 int xx=x+dir[i][0],yy=y+dir[i][1]; 71 if(xx<1||xx>n||yy<1||yy>m||pic[xx][yy]=='#')continue; 72 if(isdigit(pic[xx][yy])){ ///走到了有金币的位置 73 if(temp.fg&(1<<(pic[xx][yy]-'0'))){ ///金币已经吃过了 74 if(!vis[xx][yy][temp.fg][temp.v]){ 75 vis[xx][yy][temp.fg][temp.v]=1; 76 temp.x=xx;temp.y=yy; 77 q.push(temp); 78 } 79 } 80 else{ ///金币还没吃过 81 temp.fg|=(1<<(pic[xx][yy]-'0')); 82 temp.v++; 83 if(!vis[xx][yy][temp.fg][temp.v]){ 84 vis[xx][yy][temp.fg][temp.v]=1; 85 temp.x=xx;temp.y=yy; 86 q.push(temp); 87 } 88 } 89 } 90 else{ 91 if(!vis[xx][yy][temp.fg][temp.v]){ 92 vis[xx][yy][temp.fg][temp.v]=1; 93 temp.x=xx;temp.y=yy; 94 q.push(temp); 95 } 96 } 97 } 98 } 99 printf("-1 "); 100 } 101 int main(){ 102 int i,j,group,Case=0; 103 scanf("%d",&group); 104 while(group--){ 105 int gold=0;dcnt=0;///gold是将'C'转换为数字,方便状态压缩 106 mst(vis,0); 107 scanf("%d%d%d",&n,&m,&k); 108 node.ini(); 109 for(i=1;i<=n;++i){ 110 scanf("%s",pic[i]+1); 111 for(j=1;j<=m;++j){ 112 if(pic[i][j]=='C') pic[i][j]='0'+gold++; 113 else if(pic[i][j]=='P'){ 114 dx[dcnt]=i;dy[dcnt++]=j; 115 vis[i][j][0][0]=1; 116 } 117 else if(pic[i][j]=='E'){ 118 tx=i;ty=j; 119 } 120 else if(pic[i][j]=='S'){ 121 node.x=i;node.y=j; 122 } 123 } 124 } 125 bfs(); 126 } 127 return 0; 128 }