您的位置:首页 > 其它

hdu 1429 胜利大逃亡(续) (bfs+状态压缩)

2013-10-01 11:35 477 查看
又开始刷题了

题意:略过。

分析:主要是确定状态量,除了坐标(x,y)之外,还有一个key状态,就好比手上拿着一串钥匙。状态可以用位运算来表示:key&(x,y)表示判断有没有这扇门的钥匙,key|(x,y)表示捡起了一把钥匙。

错误:1、开标记数组mark[][][],key状态大小顺手开成key,其实应该是1<<key

2、判断应该先判wall(),顺序颠倒倒是RE(访问越界)

   3、key<=10:只有 a-j 共10种钥匙

思考:这道题其实应该是有漏洞的,因为魔王只是查看男主是否在原位置上,并没有说明检查钥匙,如此一来男主只要在时间限定T之内找到一把钥匙,就向逃亡迈进了一步,换句话说就是状态被大幅度增加——不再是必须在T内找到出口“^”。进一步说,若魔王发现男主不在原位置,不仅把他放回原位,还还原钥匙的位置,那么如果在时间限定T内,他能够找到钥匙并返回原位,又是否算是通过了这次检查呢?以上两种情况但凡一种成立,测试样例2都可以通过。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<queue>
#include<algorithm>
using namespace std;

const int MAXN=22;
const int KEY=10;

int dir[4][2]={0,-1,0,1,-1,0,1,0};

struct Node{
int x,y,t,key;
Node(){}
Node(int _x,int _y,int _t,int _key):x(_x),y(_y),t(_t),key(_key){}
};

char g[MAXN][MAXN];
int mark[MAXN][MAXN][1<<KEY];
queue<Node>q;

int n,m,T;

bool wall(int x,int y)
{
if(x<0||x>=n||y<0||y>=m)
return true;
if(g[x][y]=='*')
return true;
return false;
}

int Num(char ch)
{
return ch-(isupper(ch)?'A':'a');
}

int bfs(int sx,int sy)
{
while(!q.empty())
q.pop();

memset(mark,0,sizeof(mark));
q.push(Node(sx,sy,0,0));
while(!q.empty())
{
Node e=q.front();q.pop();

if(e.t>=T)
break;

for(int i=0;i<4;i++)
{
int dx=e.x+dir[i][0];
int dy=e.y+dir[i][1];
int dt=e.t+1;
int dkey=e.key;

char ch=g[dx][dy];

if(wall(dx,dy))
continue;
if(dt>=T||mark[dx][dy][dkey])
continue;
if(isupper(ch)&&!(dkey&(1<<Num(ch))))
continue;
if(islower(ch))
dkey=dkey|(1<<Num(ch));

if(g[dx][dy]=='^')
return dt;

mark[dx][dy][dkey]=1;
q.push(Node(dx,dy,dt,dkey));
}
}
return -1;
}

int main()
{
while(~scanf("%d%d%d",&n,&m,&T))
{
for(int i=0;i<n;i++)
scanf("%s",g[i]);

int sx,sy,ex,ey;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(g[i][j]=='@'){
sx=i;
sy=j;
g[i][j]='.';
}

printf("%d\n",bfs(sx,sy));
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: