题目大意:
孙悟空要找到一条花费时间最短的路径,路上为S的代表有蛇,经过需多花一分钟,其他情况下都是走过花费一分钟,但数字必须依次得到,最后到了唐僧处,可以经过也可以救出,救出前提是得到所有种类的钥匙
这道题,我们不断找到到达每一个点的不同状态下的最小花费时间,用dp[N][N][11][status]来存,status代表所有蛇的状态,因为蛇只有5条,所以status<32,不会爆掉。
类似spfa中不断对某个状态进行弛缓操作,如果成功就更新数据后入队,否则不再入队。
这题之所以不能dfs来做,是因为dfs不断从一个点出发搜索一条连续的值,这里因为可以重复经过,也无法设置visit量,而且对于某一点来说到起点的曼哈顿距离都是一样的,由前一个状态确认下一个状态的最好方法还是bfs,bfs过程需要注意什么时候入队,出队,数据的更新。dfs重复操作太多,也会超时。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 8 #define N 102 9 int pos[N][N]; 10 11 struct Node{ 12 int x,y,key,status; 13 }; 14 15 char mat[N][N]; 16 int dp[N][N][11][1<<5],n,m; 17 int a,b,c,d,s[N][N]; 18 int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}; 19 queue<Node> q; 20 21 void ok(Node p1,Node p2,int x) 22 { 23 if(dp[p2.x][p2.y][p2.key][p2.status]>dp[p1.x][p1.y][p1.key][p1.status]+x) 24 { 25 dp[p2.x][p2.y][p2.key][p2.status]=dp[p1.x][p1.y][p1.key][p1.status]+x; 26 //printf("%d %d %d ",p2.x,p2.y,dp[p2.x][p2.y][p2.key][p2.status]); 27 q.push(p2); 28 } 29 } 30 31 void bfs(int x,int y) 32 { 33 while(!q.empty()) 34 q.pop(); 35 36 Node t; 37 t.x=x,t.y=y,t.key=0,t.status=0; 38 q.push(t); 39 while(!q.empty()){ 40 41 Node p1 = q.front(); 42 q.pop(); 43 44 for(int i=0;i<4;i++){ 45 Node p2; 46 p2.x = p1.x+dir[i][0]; 47 p2.y = p1.y+dir[i][1]; 48 if(p2.x>=0&&p2.x<n&&p2.y>=0&&p2.y<n&&mat[p2.x][p2.y]!='#'){ 49 if(mat[p2.x][p2.y]=='.'){ 50 p2.key = p1.key; 51 p2.status = p1.status; 52 //kcout<<"in.."<<endl; 53 if(dp[p2.x][p2.y][p2.key][p2.status]>dp[p1.x][p1.y][p1.key][p1.status]+1) 54 { 55 //cout<<"in.."<<endl; 56 dp[p2.x][p2.y][p2.key][p2.status]=dp[p1.x][p1.y][p1.key][p1.status]+1; 57 q.push(p2); 58 } 59 } 60 61 else if(mat[p2.x][p2.y]=='S'){ 62 int ins = pos[p2.x][p2.y]; 63 //cout<<"inS"<<endl; 64 if(p1.status & 1<<(ins-1)){ 65 p2.key = p1.key; 66 p2.status = p1.status; 67 if(dp[p2.x][p2.y][p2.key][p2.status]>dp[p1.x][p1.y][p1.key][p1.status]+1) 68 { 69 // cout<<"inS"<<endl; 70 dp[p2.x][p2.y][p2.key][p2.status]=dp[p1.x][p1.y][p1.key][p1.status]+1; 71 q.push(p2); 72 } 73 } 74 else{ 75 p2.key = p1.key; 76 p2.status = p1.status|1<<(ins-1); 77 if(dp[p2.x][p2.y][p2.key][p2.status]>dp[p1.x][p1.y][p1.key][p1.status]+2) 78 { 79 // cout<<"inS"<<endl; 80 dp[p2.x][p2.y][p2.key][p2.status]=dp[p1.x][p1.y][p1.key][p1.status]+2; 81 q.push(p2); 82 } 83 } 84 85 } 86 87 else if(mat[p2.x][p2.y]=='T'){ 88 p2.key = p1.key; 89 p2.status = p1.status; 90 91 if(p1.key == m){ 92 if(dp[p2.x][p2.y][p2.key][p2.status]>dp[p1.x][p1.y][p1.key][p1.status]+1) 93 { 94 dp[p2.x][p2.y][p2.key][p2.status]=dp[p1.x][p1.y][p1.key][p1.status]+1; 95 } 96 } 97 else{ 98 if(dp[p2.x][p2.y][p2.key][p2.status]>dp[p1.x][p1.y][p1.key][p1.status]+1) 99 { 100 dp[p2.x][p2.y][p2.key][p2.status]=dp[p1.x][p1.y][p1.key][p1.status]+1; 101 } 102 q.push(p2); 103 } 104 } 105 106 else{ 107 int tmp = mat[p2.x][p2.y] - '0'; 108 if(tmp == p1.key+1) { 109 p2.key = p1.key+1; 110 p2.status = p1.status; 111 ok(p1,p2,1); 112 } 113 else{ 114 p2.key = p1.key; 115 p2.status = p1.status; 116 ok(p1,p2,1); 117 } 118 } 119 } 120 } 121 } 122 } 123 124 int main() 125 { 126 while(~scanf("%d%d",&n,&m)){ 127 if(n==0&&m==0) 128 break; 129 130 int tmp = 0; 131 memset(dp,0x3f,sizeof(dp)); 132 133 for(int i=0;i<n;i++){ 134 for(int j=0;j<n;j++){ 135 cin>>mat[i][j]; 136 if(mat[i][j] == 'K') 137 a=i,b=j; 138 else if(mat[i][j] == 'T') 139 c=i,d=j; 140 141 else if(mat[i][j] == 'S') 142 pos[i][j]=++tmp; 143 } 144 } 145 146 //确定孙悟空出发点后可以把当前点想象成和'.'一样的功能 147 mat[a][b] = '.'; 148 dp[a][b][0][0] = 0; 149 bfs(a,b); 150 151 int minn = 0x3f3f3f3f; 152 153 for(int i = 0;i<32;i++){ 154 //printf("%d ",dp[c][d][m][i]); 155 if(dp[c][d][m][i]<minn) 156 minn = dp[c][d][m][i]; 157 } 158 159 if(minn == 0x3f3f3f3f) 160 printf("impossible "); 161 else 162 printf("%d ",minn); 163 } 164 return 0; 165 }