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\n",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\n",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\n");
161         else
162             printf("%d\n",minn);
163     }
164     return 0;
165 }
时间: 2024-08-07 12:42:35

HDU 5025 状态压缩蛇+bfs+dp的相关文章

hdu 5180 状态压缩 dp 打表

hdu 5180 状态压缩 dp 打表 题意: 在n*n的国际象棋中,放置若干个国王和k个车,使得国王之间不互相攻击,车之间不互相攻击,车不可攻击到国王(这并不代表国王不能攻击到车).国王能攻击到它上下左右,左上左下右上右下八个位置的棋子,车可以攻击到同一行或同一列中的棋子,求方案总数对1000000007取模后的值. 限制: 1 <= n <=15; 0 <= k <=15 思路: 状态压缩,dp,打表套打表 打表程序如下: 打表程序1: tab[a][b]表示a*b的棋盘王的放

hdu 4917Permutation(状态压缩DP)

hdu 4917Permutation(状态压缩DP) 题意:将1~n的n个数排列成序列(n<=40),但有m(m<=20)个限制条件,其中第i个限制条件的表示为ai,bi.表示该序列的第ai的数要小于第bi的.问有多少中排列?保证有解 解法:我们首先可以明确一点,这m个限制条件,所表示的关系会构成若干个DAG(有向无环图,我将其称之为拓扑图).我们只要将这n个数,填入到拓扑图上,使其满足拓扑关系,那么这样的序列就是可以的.而这若干个拓扑图之间,是不会相互影响的,因而我们可以单独考虑每一个拓扑

hdu4336之状态压缩慨率DP

Card Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2141    Accepted Submission(s): 1008 Special Judge Problem Description In your childhood, do you crazy for collecting the beautifu

POJ1753 状态压缩(+BFS) + 棋盘问题

0 棋盘问题,改变一个子的颜色,这个子以及这个子周围的四个位置(左右上下)的子分别变色,求最少的改变次数. 此类题大部分应该可以用状态压缩+暴力搜索解决.纯粹找规律不太合理. 1)第一种方法,状态压缩后BFS暴力搜索.因为棋盘很小,只有16个格子,枚举所有的状态共有2^16=65536种.所以有可以用int数组存储65535个状态用以确认哪一个出现了哪一个没出现,然后暴力枚举+BFS的搜索方式. 2)第二种,或者不进行状态压缩,直接按顺序,确定改变次数为1.改变次数为2...改变次数为16,在每

(hiho1048)POJ2411Mondriaan&#39;s Dream(DP+状态压缩 or 轮廓DP)

问题: Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangle

[ACM] HDU 5025 Saving Tang Monk (状态压缩,BFS)

Saving Tang Monk Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 941    Accepted Submission(s): 352 Problem Description <Journey to the West>(also <Monkey>) is one of the Four Great Clas

hdu 5135 状态压缩dp

题意是给出最对12条边你     问最大可组成三角形面积是多大 (可有多个三角形)   典型的状态压缩  (最多12条边) 思路: 先暴力枚举所有可能三角形的面积   然后再根据状态压缩来做    最多可组成n/3个三角形  对每个三角形都记录三边或(运算)    和面积    然后判断进行合并  (根据且运算)   就行了 #include<stdio.h> #include<string.h> #include<cmath> #include<iostream

[HDU]5094Maze(状态压缩BFS)

状态压缩的题,第一次WA了,怎么改都不对,交了十几遍,之后重新写了一个,1A了 #include<cstdio> #include<queue> #include<cstring> #include<algorithm> using namespace std; const int maxn = 51; const int dir[4][2] = {{0,1},{-1,0},{0,-1},{1,0}}; int n,m,t; int door[maxn][m

hdu 3811 状态压缩

题意就不对说了:  开始想用深搜过  感觉数据水的话应该能过,  哈哈  还是超时了!!! 正确做法应该是状态压缩吧,n小于等于17    2^17-1种状态,每种状态表示对应的数用没用过,如果用状态压缩dp的思路(从小状态跑到大状态)的话就不对了,开始一直没想明白,仔细想想也是,如果按以前的 就会改变dp里面的值,实际上对每一种状态的值是一定的,还有就是为什么要跑结果的对立面,看看测试数据   ,两个要求之间是有重复的,比如1,1和2,2    这样跑起来就不方便. 跑的时候三重for   外