题意:在一个迷宫中,有一些宝物,从起点走到终点,问在给定的时间内,到达终点后所能拾取珠宝的最大价值。
分析(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