原题网址:http://bailian.openjudge.cn/practice/4105/
思路:
每个位置包括的状态:所在的位置,获得的宝石。
广搜:用队列存储达到某个位置时,获得的宝石完全相同的最少用时。
传送门另外考虑即可。
详细代码:
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 using namespace std; 5 6 const int INF = 0x44444444; 7 int gater[10], gatec[10], cnt, n,m, k, dp[210][210][1<<5],// 存储传送门的数量,到大某个位置时,获得宝石完全相同时的最少用时 8 ex,ey; 9 char mp[210][210]; 10 queue<int> que; 11 12 int main(){ 13 freopen("C:\Users\yyf\Documents\CppFiles\in.txt", "r", stdin); 14 int t,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1}; 15 scanf("%d", &t); 16 while(t--){ 17 cnt=0; 18 memset(dp, 0x44, sizeof(dp)); 19 scanf("%d%d%d", &n, &m, &k); 20 for(int i=0; i<n; ++i){ 21 scanf("%s", mp[i]); 22 for(int j=0; j<m; ++j){ 23 switch(mp[i][j]){ 24 case '$': gater[cnt]=i;gatec[cnt++]=j; 25 break; 26 case 'S': que.push(i), que.push(j), que.push(0); 27 dp[i][j][0]=0; 28 break; 29 case 'E': ex=i, ey=j; break; 30 default : break; 31 } 32 } 33 } 34 while(!que.empty()){ 35 int tr = que.front(); que.pop(); 36 int tc = que.front(); que.pop(); 37 int ts = que.front(); que.pop(); 38 for(int i=0; i<4; ++i){// 四个方向 39 int r=tr+dx[i], c=tc+dy[i]; 40 if(r<0 || c<0 || r==n || c==m || mp[r][c]=='#') continue; 41 int t = dp[tr][tc][ts]+1, s=ts; 42 if('0'<=mp[r][c] && mp[r][c]<='4'){ 43 s |= 1<<mp[r][c]-'0'; 44 } 45 if(t>=dp[r][c][s]) continue;// 剪枝 46 if(mp[r][c]=='$'){ 47 for(int j=0; j<cnt; ++j){ 48 dp[gater[j]][gatec[j]][s] = t; 49 que.push(gater[j]), que.push(gatec[j]); 50 que.push(s); 51 } 52 } 53 else { 54 dp[r][c][s]=t; 55 if(mp[r][c]=='E' && s==(1<<k)-1) continue; 56 que.push(r), que.push(c), que.push(s); 57 } 58 } 59 } 60 if(dp[ex][ey][(1<<k)-1] == INF) printf("oop! "); 61 else printf("%d ", dp[ex][ey][(1<<k)-1]); 62 } 63 return 0; 64 }