其实这是一道水题,因为有人问所以做了一下。
第一次知道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