题意:在一个迷宫中,有一些宝物,从起点走到终点,问在给定的时间内,到达终点后所能拾取珠宝的最大价值。
分析(BFS+DFS):DFS特点:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高。
对整个图做bfs,bfs求得某个点(入口、出口、珠宝)到另外一个点之间的最短距离。bfs过程中构建隐式图,然后从入口处开始进行dfs搜索构造的隐式图,更新ans。
PS:该題还能用BFS+状态压缩做,但效率不高。
将宝物状态压缩,对于l个珍宝,可以用l位二进制表示珍宝的获取情况(1表示获得,0未获得)。然后用vis[i][j][k]表示状态,i表示珍宝获取情况,(j,k)表示位置。这样相当于走2^l张地图,每次得到珍宝时转换地图,这样就需要相当多的时间消耗了。在bfs+dfs中,珍宝至多10件,可以找出起点到所有珍宝和终点的最短路径,珍宝到其他珍宝和终点的最短路径。需要bfs地图至多21次,比上面的2^l次要少很多。因此BFS+DFS效率高。
#include<iostream> #include<queue> using namespace std; #define N 60 int W,H,L,M; //地图是W列H行,时间限制L,宝石数量M int val[N]; //宝石的价值 char map[N][N]; //地图 bool bfsvis[N][N]; //BFS访问标记 bool dfsvis[N]; //dfs访问标记 int step[N][N]; //bfs中访问步长 int ans,sum; //结果,宝石总价值 int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}}; int dis[N][N]; //记录开始位置,结束位置,各宝石位置两两之间的距离 void BFS(int cx,int cy,int s) //求解(cx,cy)到其他点的距离,s(0-M+1),0表示开始位置,M+1出口,其他宝石位置 { queue<int> q; int u,i,x,y,x2,y2; memset(bfsvis,false,sizeof(bfsvis)); memset(step,0,sizeof(step)); u=cx*W+cy; //初始点 q.push(u); bfsvis[cx][cy]=true; step[cx][cy]=0; while(!q.empty()) { u=q.front(); q.pop(); x=u/W; y=u%W; for(i=0;i<4;i++) //四个方向 { x2=x+dir[i][0]; y2=y+dir[i][1]; if(x2<0||x2>=H||y2<0||y2>=W||bfsvis[x2][y2]||map[x2][y2]=='*') continue; bfsvis[x2][y2]=true; step[x2][y2]=step[x][y]+1; //步长加1 if(map[x2][y2]=='@') dis[s][0]=step[x2][y2]; //其他点到起点 else if(map[x2][y2]=='<') dis[s][M+1]=step[x2][y2]; //其他点到终点 else if(map[x2][y2]>='A' && map[x2][y2]<='J') //其他点到宝石点 dis[s][map[x2][y2]-'A'+1]=step[x2][y2]; q.push(x2*W+y2); } } } void DFS(int s,int value,int t) //s当前点,value当前获得的价值,t当前花费的时间 { int i; if(t>L) //超时 return ; if(ans==sum) //宝石已全部获取,剪枝 return ; if(s>M) //已到出口 { if(value>ans) ans=value; return ; } for(i=0;i<=M+1;i++) { if(dis[s][i]==0 || dfsvis[i]) //自己到自己或者已经访问过 continue; dfsvis[i]=true; DFS(i,value+val[i],t+dis[s][i]); dfsvis[i]=false; } } int main() { int T,i,j,t=0; scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&W,&H,&L,&M); sum=0; for(i=1;i<=M;i++) { scanf("%d",&val[i]); sum+=val[i]; } val[0]=val[M+1]=0; for(i=0;i<H;i++) scanf("%s",map[i]); memset(dis,0,sizeof(dis)); for(i=0;i<H;i++) //BFS对相关点处理 for(j=0;j<W;j++) if(map[i][j]=='@') BFS(i,j,0); else if(map[i][j]=='<') BFS(i,j,M+1); else if(map[i][j]>='A' && map[i][j]<='Z') BFS(i,j,map[i][j]-'A'+1); ans=-1; memset(dfsvis,false,sizeof(dfsvis)); dfsvis[0]=true; DFS(0,0,0); cout<<"Case "<<++t<<":"<<endl; if(ans>=0) cout<<"The best score is "<<ans<<"."<<endl; else cout<<"Impossible"<<endl; if(T>0) cout<<endl; } return 0; }
HDU ACM 1044 Collect More Jewels BFS+DFS
原文地址:http://blog.csdn.net/a809146548/article/details/46381003