其实这是一道水题,因为有人问所以做了一下。
第一次知道HDOJ AC数1000+的题目我也可以写将近一个小时。。
一道诡异的水题搞得我整个中午都诡异了。。。
俗话说的好,做水题伤身。
俗话又说的好,做水题还犯脑残错误更伤身。
俗话还说的好,脑残无药医啊啊啊啊啊啊啊啊
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1180
题目大意:
给定一个n*m的地图,给定了起点S和终点T。
某些格子上有障碍,有些格子上有楼梯。
有障碍的格子不能走,有楼梯的格子只有楼梯的方向跟行进方向相同时才能走。
楼梯每分钟变换一次方向(横向或竖向)。
每走一步花费1分钟,走楼梯的话可以直接走到楼梯对面,也是花费一分钟。
没有两个相邻的楼梯,人不能在楼梯上停留。
求需花费的最小时间。
算法:
简单的BFS。
显然距离要保留两个量,分别对应时间是奇数和时间是偶数时。
因为每次搜索到下一层的节点时,不管是走平地、走楼梯还是站着不动,时间都必定会加1,所以队列中的节点符合时间上的单调性。
还要注意一下在原地不动的情况。只有在S、T以及空地处才可以停留。
代码如下:
身心健康BFS版:
#include<cstdio> #include<algorithm> #include<queue> #include<cstring> #define st first #define nd second #define mp make_pair using namespace std; typedef pair<int,int> PII; const int MAXN=50; char s[MAXN][MAXN]; int mm[MAXN][MAXN]; int d[MAXN][MAXN][2]; int dx[5]= {1,-1,0,0,0}; int dy[5]= {0,0,1,-1,0}; queue<PII>q; int n,m; int get_id(int x, int y) { return (x-1)*m+y-1; } int main() { while(scanf("%d%d",&n,&m)==2) { memset(d,-1,sizeof(d)); memset(mm,-1,sizeof(mm)); for(int i=0; i<n; i++) { scanf("%s",s[i]); } int S,T; for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(s[i][j]=='|') { mm[i+1][j+1]=0; } else if(s[i][j]=='-') { mm[i+1][j+1]=1; } else if(s[i][j]=='.') { mm[i+1][j+1]=2; } else if(s[i][j]=='S') { S=get_id(i+1,j+1); mm[i+1][j+1]=2; } else if(s[i][j]=='T') { T=get_id(i+1,j+1); mm[i+1][j+1]=2; } } } while(!q.empty()) { q.pop(); } q.push(mp(S,0)); d[S/m+1][S%m+1][0]=0; while(!q.empty()) { int x=q.front().st; if(x==T) { break; } int y=x%m+1; x=x/m+1; int state=q.front().nd; q.pop(); for(int i=0; i<5; i++) { int nx=x+dx[i]; int ny=y+dy[i]; if(mm[nx][ny]==-1) { continue; } if((mm[nx][ny]<2)&&((mm[nx][ny]^state)==(i>>1))) { nx+=dx[i]; ny+=dy[i]; } else if((mm[nx][ny]<2)&&((mm[nx][ny]^state)!=(i>>1))) { continue; } if(mm[nx][ny]==-1) { continue; } if(d[nx][ny][state^1]==-1||d[nx][ny][state^1]>d[x][y][state]+1) { d[nx][ny][state^1]=d[x][y][state]+1; q.push(mp(get_id(nx,ny),state^1)); } } } if(d[T/m+1][T%m+1][0]!=-1&&d[T/m+1][T%m+1][1]!=-1) { printf("%d\n",min(d[T/m+1][T%m+1][0],d[T/m+1][T%m+1][1])); } else { printf("%d\n",max(d[T/m+1][T%m+1][0],d[T/m+1][T%m+1][1])); } } return 0; }
闲的蛋疼A*版:
其实为什么叫它闲的蛋疼A*版呢,因为这道题本来就跑了0ms,我就是再优化也看不出效果来。
那么既然如此为什么还要写A*了呢,因为我闲的蛋疼啊。。
至于我为什么闲的蛋疼呢?
让你连着上一个礼拜数院的专业课,你试试。。
不仅讲得很难,而且讲得很快,所幸完全听不懂,好在是上全天。
呵呵呵呵。。。俗话说得好。。。
you say he can't, you can you up.
#include<cstdio> #include<algorithm> #include<queue> #include<vector> #include<cstring> #define st first #define nd second #define mp make_pair using namespace std; typedef pair<int,int> PII; const int MAXN=50; char s[MAXN][MAXN]; int mm[MAXN][MAXN]; int d[MAXN][MAXN][2],h[MAXN*MAXN]; bool vis[MAXN][MAXN][2]; int dx[5]= {1,-1,0,0,0}; int dy[5]= {0,0,1,-1,0}; int n,m; struct cmp { bool operator()(const pair<PII,int>& a, const pair<PII,int>& b) { return a.st.nd+h[a.st.st]>b.st.nd+h[b.st.st]; } }; priority_queue <pair<PII,int> , vector<pair<PII,int> >, cmp> q; int get_id(int x, int y) { return (x-1)*m+y-1; } void bfs(int S) { memset(h,-1,sizeof(h)); h[S]=0; queue<int>q; q.push(S); while(!q.empty()) { int x=q.front(); int y=x%m+1; x=x/m+1; q.pop(); for(int i=0; i<4; i++) { int nx=x+dx[i]; int ny=y+dy[i]; if(mm[nx][ny]==-1) { continue; } if(h[get_id(nx,ny)]==-1) { h[get_id(nx,ny)]=h[get_id(x,y)]+1; q.push(get_id(nx,ny)); } } } } int main() { while(scanf("%d%d",&n,&m)==2) { memset(d,-1,sizeof(d)); memset(mm,-1,sizeof(mm)); memset(vis,0,sizeof(vis)); for(int i=0; i<n; i++) { scanf("%s",s[i]); } int S,T; for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(s[i][j]=='|') { mm[i+1][j+1]=0; } else if(s[i][j]=='-') { mm[i+1][j+1]=1; } else if(s[i][j]=='.') { mm[i+1][j+1]=2; } else if(s[i][j]=='S') { S=get_id(i+1,j+1); mm[i+1][j+1]=2; } else if(s[i][j]=='T') { T=get_id(i+1,j+1); mm[i+1][j+1]=2; } } } bfs(S); while(!q.empty()) { q.pop(); } q.push(mp(mp(S,0),0)); d[S/m+1][S%m+1][0]=0; while(!q.empty()) { int x=q.top().st.st; if(x==T) { break; } int y=x%m+1; x=x/m+1; int state=q.top().nd; q.pop(); if(vis[x][y][state]) { continue; } vis[x][y][state]=true; for(int i=0; i<5; i++) { int nx=x+dx[i]; int ny=y+dy[i]; if(mm[nx][ny]==-1) { continue; } if((mm[nx][ny]<2)&&((mm[nx][ny]^state)==(i>>1))) { nx+=dx[i]; ny+=dy[i]; } else if((mm[nx][ny]<2)&&((mm[nx][ny]^state)!=(i>>1))) { continue; } if(mm[nx][ny]==-1) { continue; } if(d[nx][ny][state^1]==-1||d[nx][ny][state^1]>d[x][y][state]+1) { d[nx][ny][state^1]=d[x][y][state]+1; q.push(mp(mp(get_id(nx,ny),d[nx][ny][state^1]),state^1)); } } } if(d[T/m+1][T%m+1][0]!=-1&&d[T/m+1][T%m+1][1]!=-1) { printf("%d\n",min(d[T/m+1][T%m+1][0],d[T/m+1][T%m+1][1])); } else { printf("%d\n",max(d[T/m+1][T%m+1][0],d[T/m+1][T%m+1][1])); } } return 0; }
PS:求有时间的大神帮我试一下迭代加深dfs跑的怎么样啊。。。实在是没那个心力了。。。orz