HDU 5025 状态压缩蛇+bfs+dp

题目大意:
孙悟空要找到一条花费时间最短的路径,路上为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 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/3991885.html