题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2612
方法:其实就是从两个点分别探寻单源最短路径,两个点到同一个目标位置的最短路径都求出来,相加,然后找出到哪一个相同目标位置的最短路径之和最小即可,采用的模拟dijsktral算法。
要注意的一个地方是,找到一个kfc后一定还要继续去找,而不是向其他广搜题那样就停止探寻了,不能有思维定势啊。
实现方法为,初始的时候将两个源点到目标位置的距离设置为正无穷,然后分别用单元最短路径的算法模拟广搜并更新到目标位置的距离,最后在目标位置中找到最短路径之和最小的,由于正无穷和任何数之和都是正无穷,所以如果遇到不是被两个源点都可以达目标位置时,起路径和为正无穷,在比较的时候都会被忽略掉。
除此之外,记录目标位置坐标的数组不能开在200内,这里要细心,这里最多可以用接近4万个。
感想:思维定势造成一个下面如此简单的测试数据拜掉,wa了很久。
3 5
Y...@
####@
M....
代码:
View Code
#include <iostream> #include <queue> #include<algorithm> using namespace std; int n,m; char map[202][202]; int dY[202][202]; int dM[202][202]; const char wall='#'; const char road='.'; const char Y='Y'; const char M='M'; const char KFC='@'; const int MAX=0x7fffffff; int YposX,YposY,MposX,MposY; bool v[202][202]; int deriction[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; struct Step { int x,y; int currentUsedTime; }; void BFSSearch(char who) { memset(v,false,sizeof(v)); int x = who == Y ? YposX:MposX; int y = who == Y ? YposY:MposY; Step step; step.x = x; step.y = y; step.currentUsedTime = 0; queue<Step> q; q.push(step); while(!q.empty()) { Step t_step = q.front(); q.pop(); if(!v[t_step.x][t_step.y]) { v[t_step.x][t_step.y]= true; if(map[t_step.x][t_step.y]==KFC) { if(who == Y && dY[t_step.x][t_step.y]>t_step.currentUsedTime) dY[t_step.x][t_step.y]=t_step.currentUsedTime; if(who == M && dM[t_step.x][t_step.y]>t_step.currentUsedTime) dM[t_step.x][t_step.y]=t_step.currentUsedTime; } //下面的部分不能放在与上面对应的else里面,找一个kfc还要继续找, //这样才符合dijsktral算法的特点。 //不要受一般广搜的思维定势限制。 //否则下面测试数据肯定要败掉 /* 3 5 Y...@ ####@ M.... */ int n_x,n_y; Step n_step; for(int i =0;i<4;i++) { n_x = t_step.x+deriction[i][0]; n_y = t_step.y+deriction[i][1]; if(map[n_x][n_y]!=wall && !v[n_x][n_y]) { n_step.x=n_x; n_step.y=n_y; n_step.currentUsedTime = t_step.currentUsedTime+1; q.push(n_step); } } } } } int MyAdd(int x,int y) { if(x==MAX ||y ==MAX) return MAX; return x+y; } int MyCmp(int x,int y) { return x<y ? x : y; } void main() { while(scanf("%d %d",&n,&m)!=EOF) { memset(map,wall,sizeof(map)); memset(dY,0,sizeof(dY)); memset(dM,0,sizeof(dM)); int recordKFC[40000][2]; int k=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>map[i][j]; if(map[i][j] == Y) { YposX = i; YposY=j; } if(map[i][j] == M) { MposX = i; MposY=j; } if(map[i][j] == KFC) { dY[i][j] = dM[i][j] = MAX; recordKFC[k][0] = i; recordKFC[k][1] = j; k++; } } BFSSearch(Y); BFSSearch(M); int re = MAX; for(int x=0;x<k;x++) re = MyCmp(re, MyAdd(dY[ recordKFC[x][0] ] [ recordKFC[x][1] ],dM[ recordKFC[x][0] ] [ recordKFC[x][1] ] )); cout<<11*re<<endl; } }