好久没有更新空间了,上学期心思都花在同学身上了,结局十分悲摧..目前转移注意力到acm上来.
队里在训练搜索 我这种水货也跟着打打酱油吧.
hdu 2128 Tempter of the Bone II
这个题应该是hdu1010的加强版吧
题意就是 地图上有个起点S 终点D 还有一些障碍物X和 1--9炸弹可以捡 doggie可以上下左右四个方向走 遇到障碍物如果有炸弹可以炸开 花费1秒钟
问走到出口最少时间
地图8x8 我没有试过深度优先搜索 比如迭代dfs
我直接用堆队列宽搜 时间小的在堆顶嘛
然后就是状态的判重
这题听他们说HDU数据很弱 所以好多错的方法都过了...
不知道别人怎么做的 说下我的方法
由于这个doggie地图上走来走去 会炸障碍物 会捡炸弹 所以会破坏地图
所以我们搜索的同时可能要保存地图
这里地图是8x8==64 我用的位压缩保存 unsigned long long 2^64-1 刚好64位
地图从上到下从左到右格子分别标记为0--n*m-1号
这样位与格子就对应起来了
未压缩里有意义的只有炸弹和障碍物的格子 因为其他格子不会变的
我的未压缩里 如果一个障碍物格子或者炸弹格子对应的为是0,说明没有走过,1则表示走过的.
这里unsigned long long数量有点大 不过是离散的 我用的红黑树map保存
map<ULL,int> visited[N][N];
visited[x][y][k] 表示到[x,y]这个点,地图状态为k的最小时间 如果后面也可以到这个状态 但时间比当前的时间要长 就不用继续搜索了.
可能有的人会问这样时间复杂度够吗 乘了一个logM 我也不好说 这个有一定期望在里面 总的来说是过得去的 再说了 反正优先队列已经有了一个logM了 怕什么 正确率优先嘛...
我真不知道0ms是怎么出来的...
附点数据:
8 8
......XD
.XXXX..X
.XXXXX..
.XXXXXXX
.XXXXXXX
...4XXXX
XXXXXXX3
XXXXXXXS
38
6 5
S.XX1
X.1X1
XX.X.
XXXXX
XXXXX
XXXDX
17
6 6
S1XX3X
XXXXXX
2XXXXX
XXXXXX
XXXXXX
X1XDXX
29
5 6
S.XXXX
21..XX
XXXXXX
XXXXXX
3XXXDX
11
5 3
S..
1X.
XX.
...
XXD
6
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
typedef unsigned long long ULL;
const int MAXN = 8;
const int INF = 0x3fffffff;
char mapx[MAXN][MAXN];
map<ULL,int> visited[MAXN][MAXN];
int dir[4][2]= //下 右 上 左 四个方向
{
{1,0},
{0,1},
{-1,0},
{0,-1}
};
int n,m;
int ai,aj,bi,bj; //起点 终点
struct State
{
int x,y,e;
int time;
ULL flg;
State(int _x=0,int _y=0,int _e=0,int _time=0,ULL _flg=0)
{x=_x;y=_y;e=_e;time=_time;flg=_flg;}
bool operator < (const State & v) const //小根堆
{
return time>v.time;
}
};
void InputData()
{
for(int i=0;i<n;i++)
{
while(getchar()!='\n');
for(int j=0;j<m;j++)
{
mapx[i][j]=getchar();
if(mapx[i][j]=='S')
ai=i,aj=j;
else
if(mapx[i][j]=='D')
bi=i,bj=j;
}
}
}
bool is_legal(int x,int y)
{
if(x<0 || x>=n || y<0 || y>=m)
return false;
return true;
}
int Bfs()
{
priority_queue<State> q;
for(int i=0;i<MAXN;i++)
{
for(int j=0;j<MAXN;j++)
visited[i][j].clear();
}
q.push(State(ai,aj,0,0,0));
visited[ai][aj][0]=0;
while(!q.empty())
{
State u=q.top();
q.pop();
if(u.time>visited[u.x][u.y][u.flg])
continue;
if(u.x==bi && u.y==bj)
return u.time;
for(int c=0;c<4;c++)
{
//产生下一格横纵坐标
int nx=u.x+dir[c][0];
int ny=u.y+dir[c][1];
if(!is_legal(nx,ny))
continue;
int k=nx*m+ny;
if(mapx[nx][ny]=='X')
{
if(!(u.flg & ((ULL)1<<k))) //如果下一格没有走过
{
map<ULL,int>::iterator it=visited[nx][ny].find(u.flg|((ULL)1<<k));
int num=(it==visited[nx][ny].end())?INF:it->second;
if(u.e>=1 && num>u.time+2)
{
visited[nx][ny][u.flg|((ULL)1<<k)]=u.time+2;
q.push(State(nx,ny,u.e-1,u.time+2,u.flg|((ULL)1<<k)));
}
}
else
{
map<ULL,int>::iterator it=visited[nx][ny].find(u.flg);
int num=(it==visited[nx][ny].end())?INF:it->second;
if(num>u.time+1)
{
visited[nx][ny][u.flg]=u.time+1;
q.push(State(nx,ny,u.e,u.time+1,u.flg));
}
}
}
else
if(mapx[nx][ny]>='0' && mapx[nx][ny]<='9')
{
if(!(u.flg & ((ULL)1<<k)))
{
map<ULL,int>::iterator it=visited[nx][ny].find(u.flg|((ULL)1<<k));
int num=(it==visited[nx][ny].end())?INF:it->second;
if(num>u.time+1)
{
visited[nx][ny][u.flg|((ULL)1<<k)]=u.time+1;
q.push(State(nx,ny,u.e+mapx[nx][ny]-'0',u.time+1,u.flg|((ULL)1<<k)));
}
}
else
{
map<ULL,int>::iterator it=visited[nx][ny].find(u.flg);
int num=(it==visited[nx][ny].end())?INF:it->second;
if(num>u.time+1)
{
visited[nx][ny][u.flg]=u.time+1;
q.push(State(nx,ny,u.e,u.time+1,u.flg));
}
}
}
else
{
map<ULL,int>::iterator it=visited[nx][ny].find(u.flg);
int num=(it==visited[nx][ny].end())?INF:it->second;
if(num>u.time+1)
{
visited[nx][ny][u.flg]=u.time+1;
q.push(State(nx,ny,u.e,u.time+1,u.flg));
}
}
}
}
return -1;
}
int main()
{
while(scanf("%d %d",&n,&m) && (n || m))
{
InputData();
int ans=Bfs();
printf("%d\n",ans);
}
return 0;
}