4 4 Y.#@ .... .#.. @..M 4 4 Y.#@ .... .#.. @#.M 5 5 Y..@. .#... .#... @..M. #...#
66 88 66
题目大意:给一个迷宫,起点Y,终点M,Y和M要在@的地方相遇,求最短时间。不要求同时到达。
题目分析:给了起点和终点,很容易想到dbfs。不过这题保证有解,也可以dfs,而且这个迷宫问题很容易想到启发函数h(x) = 当前点到目标点的曼哈顿距离。所以可以IDA*。
这题先用dbfs交了一个,跑的速度还可以,不过dbfs的弱点,内存耗的太多,hdu上排100+,因为这题不要求同时到达,所以dbfs的时候不能找到解就输出,因为最先找到的并不一定是最优的。bfs先找到的解不是最优的?没错,具体的看我dbfs版本后面的测试数据。
后来看了下hdu排第一版的内存耗的少,估计是dfs做的,然后就改了个IDA*交上去,结果跑了200ms+,然后各种优化。。。还是跑不进200ms。。。
好吧,先上代码,如果我写挫了,请告诉我一声:D
dbfs:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> const int N = 205; const int M = 10005;//205就够了。。。这数据是有多弱。。。Orz。。。 int n,m; char map[N][N]; int flag[2][N][N]; int si,sj,ei,ej; int dx[] = {1,-1,0,0}; int dy[] = {0,0,1,-1}; struct node { int x,y,time; }ss,now; struct que { struct node t[M]; int head,tail; void init() { head = tail = 0; } bool empty() { return head == tail; } void push(struct node a) { t[tail] = a; tail ++; if(tail >= M) tail -= M; } void pop() { head ++; if(head >= M) head -= M; } struct node top() { return t[head]; } }q[2]; int Min(int a,int b) { return a > b?b:a; } int main() { int i,j,k; while(scanf("%d%d",&n,&m) != EOF) { getchar(); for(i = 1;i <= n;i ++) { for(j = 1;j <= m;j ++) { map[i][j] = getchar(); if(map[i][j] == 'Y') { si = i; sj = j; } if(map[i][j] == 'M') { ei = i; ej = j; } } getchar(); } q[0].init(); q[1].init(); ss.time = 0; ss.x = si; ss.y = sj; memset(flag,0,sizeof(flag)); flag[0][si][sj] = 1; q[0].push(ss); ss.x = ei; ss.y = ej; flag[1][ei][ej] = 1; q[1].push(ss); j = 0; int ans = 0x3fff; while(!q[0].empty() && !q[1].empty()) { for(i = 0;i <= 1;i ++) { while(!q[i].empty() && q[i].top().time == j) { now = q[i].top(); q[i].pop(); ss.time = now.time + 1; for(k = 0;k < 4;k ++) { ss.x = now.x + dx[k]; ss.y = now.y + dy[k]; if(ss.x < 1 || ss.y < 1 || ss.x > n || ss.y > m || map[ss.x][ss.y] == '#') continue; if(!flag[i][ss.x][ss.y]) { flag[i][ss.x][ss.y] = ss.time; if(flag[1 - i][ss.x][ss.y] && map[ss.x][ss.y] == '@') { ans = Min(ans,flag[1 - i][ss.x][ss.y] + ss.time); break; } q[i].push(ss); } } } } j ++; } printf("%d\n",ans * 11); } return 0; } //15MS 1252K /* 5 6 Y.#... @..... ...@#. ...##. .....M */
IDA*:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> const int N = 205; const int M = 1000005; int n,m; int ans; char map[N][N]; int flag[2][N][N];//这题判不判重都行 int si,sj,ei,ej; int dx[] = {1,-1,0,0}; int dy[] = {0,0,1,-1}; bool ok; int Abs(int a) { return a > 0?a:-a; } void Dfs(int curi,int curj,int dp) { if(ok) return; if(dp + Abs(curi - ei) + Abs(curj - ej) > ans) return; if(map[curi][curj] == 'M') { ok = true; return; } int i; //flag[1][curi][curj] = 1; for(i = 0;i < 4;i ++) { int tx = curi + dx[i]; int ty = curj + dy[i]; if(tx < 1 || ty < 1 || tx > n || ty > m || map[tx][ty] == '#')// || flag[1][tx][ty]) continue; Dfs(tx,ty,dp + 1); } //flag[1][curi][curj] = 0; } void dfs(int curi,int curj,int dp) { if(ok) return; if(dp + Abs(curi - ei) + Abs(curj - ej) > ans) return; //flag[0][curi][curj] = 1; if(map[curi][curj] == '@') { Dfs(curi,curj,dp); } int i; for(i = 0;i < 4;i ++) { int tx = curi + dx[i]; int ty = curj + dy[i]; if(tx < 1 || ty < 1 || tx > n || ty > m || map[tx][ty] == '#')// || flag[0][tx][ty]) continue; dfs(tx,ty,dp + 1); } //flag[0][curi][curj] = 0; } int main() { int i,j,k; while(scanf("%d%d",&n,&m) != EOF) { //memset(flag,0,sizeof(flag)); getchar(); for(i = 1;i <= n;i ++) { for(j = 1;j <= m;j ++) { map[i][j] = getchar(); if(map[i][j] == 'Y') { si = i; sj = j; } if(map[i][j] == 'M') { ei = i; ej = j; } // if(map[i][j] == '#') // flag[0][i][j] = flag[1][i][j] = 1; } getchar(); } ans = Abs(si - ei) + Abs(sj - ej);//迭代初始深度不必从1开始 ok = false; while(!ok) { dfs(si,sj,0); ans ++; } printf("%d\n",ans * 11 - 11); } return 0; } //265MS 440K //203MS 604K //为什么会跑这么慢。。。