题意:从1,1走到n,m。求花费最少的时间,每走一步一秒,有门,需要相应的钥匙开门。。。
比较简单的状压搜索。。。但就是坑。。。
解法就是状压BFS,将钥匙状压,用一个4维数组记录门或墙的情况,然后BFS,这里要注意的是,一个点可能有多个钥匙。。。还有可能钥匙放在起点(这个不知道是不是坑,反正我考虑了)。。
后面改了下,,代码也有点小挫。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int MAXN=56;
const int dir[4][2]={1,0,-1,0,0,1,0,-1};
int wall[MAXN][MAXN][MAXN][MAXN];
vector<int> key[MAXN][MAXN];
struct Node
{
int x,y,sta;
int step;
bool operator < (const Node &rhs) const
{
return step>rhs.step;
}
};
bool vis[MAXN][MAXN][1135];
int n,m;
int bfs(int x,int y)
{
Node cur,temp;
int i,j;
memset(vis,0,sizeof(vis));
priority_queue<Node> q;
cur.x=x;
cur.y=y;
cur.step=0;
cur.sta=0;
for(i=0;i<key[x][y].size();i++)
cur.sta=(cur.sta|(1<<key[cur.x][cur.y][i]));
q.push(cur);
vis[x][y][cur.sta]=1;
while(!q.empty())
{
cur=q.top();
q.pop();
// printf("x=%d y=%d step=%d sta=%d\n",cur.x,cur.y,cur.step,cur.sta);
if(cur.x==n&&cur.y==m)
{
return cur.step;
}
for(i=0;i<4;i++)
{
temp.x=cur.x+dir[i][0];
temp.y=cur.y+dir[i][1];
int res=wall[cur.x][cur.y][temp.x][temp.y];
if(temp.x<1||temp.x>n||temp.y<1||temp.y>m)
continue;
if(res==0)
continue;
if(res!=-1&&(cur.sta&(1<<res))==0)
continue;
temp.sta=cur.sta;
for(j=0;j<key[temp.x][temp.y].size();j++)
temp.sta=(temp.sta|(1<<key[temp.x][temp.y][j]));
temp.step=cur.step+1;
if(!vis[temp.x][temp.y][temp.sta])
{
vis[temp.x][temp.y][temp.sta]=1;
q.push(temp);
}
}
}
return -1;
}
int main()
{
int p,i,j,k;
while(scanf("%d%d%d",&n,&m,&p)==3)
{
scanf("%d",&k);
memset(wall,-1,sizeof(wall));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
key[i][j].clear();
int x1,y1,x2,y2,q;
while(k--)
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&q);
wall[x1][y1][x2][y2]=q;
wall[x2][y2][x1][y1]=q;
}
scanf("%d",&k);
while(k--)
{
scanf("%d%d%d",&x1,&y1,&q);
key[x1][y1].push_back(q);
}
int ans=bfs(1,1);
printf("%d\n",ans);
}
return 0;
}