您的位置:首页 > 其它

HDU 4444 - Walk

2012-11-08 11:51 267 查看
题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4444

2012年ACMICPC金华赛区C题。

作为我们队主攻搜索和数据结构(线段树神马的经常接触离散化),当时我一看这题就有想法了,综合起来只敲了四十多分钟。(其间分身去把被卡了N久的水题A了)

我们队就是靠这题从铁直接飞到银牌。

思路很简单。

离散化边界为点。然后就是用普通的BFS去做。

需要储存每个边的四种状态:矩形上边界?矩形下边界?矩形左边界?矩形右边界?

边拐角的问题不同于角拐角,有六种可能,比较难解决,需要多一想一想。

比较难通过的是我附录的最后一组测试数据。

当时比赛时犯2,判断以EOF结束,WA了两次。。。 没想到,回来之后在HDU交,还是犯2,又判断以EOF结束,再WA两次。。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;

int x[110],y[110];
int idx[110],idy[110];
int mp[210][210],path[210][210];
bool UP[210][210],DOWN[210][210],LEFT[210][210],RIGHT[210][210];
int ax,ay,bx,by;
int n,nn;
int mx,my;

struct QUE
{
int x,y;
QUE()
{

}
QUE(int xx,int yy)
{
x=xx,y=yy;
}
}que[200000];

int fx[]={1,0,0,-1,0,0,0,0,1,-1,1,-1};
int fy[]={0,1,-1,0,1,-1,1,-1,0,0,0,0};
int fz[]={0,0,0,0,1,1,-1,-1,-1,-1,1,1};

void turn(int ex,int ey,int rx,int ry,int &t,int p)
{
int i,nx,ny;
for(i=1;;i+=2)
{
nx=rx+ex*i;
ny=ry+ey*i;
if(nx<0 || ny<0 || nx>mx || ny>my)
{
return;
}
if(mp[nx][ny]>0)
{
return;
}
if(i>1 &&(UP[nx-ex][ny-ey]&&DOWN[nx-ex][ny-ey]&&(ny&1) || (nx&1)&&LEFT[nx-ex][ny-ey]&&RIGHT[nx-ex][ny-ey]))
{
return;
}
if(path[nx][ny]==-1)
{
que[++t]=QUE(nx,ny);
path[nx][ny]=p;
}
else if(path[nx][ny]<p)
{
return;
}
}
}

int bfs()
{
int s,t,k;
int rx,ry;
s=0;
t=-1;
for(k=0;k<4;k++)
{
turn(fx[k],fy[k],ax,ay,t,0);
}
while(s<=t)
{
rx=que[s].x;
ry=que[s].y;
++s;
for(k=0;k<4;k++)
{
if(rx+fx[k]==bx && ry+fy[k]==by)
{
return path[rx][ry];
}
}
if(rx&1)
{
for(k=4;k<8;k++)
{
if(UP[rx+fz[k]][ry]&&DOWN[rx+fz[k]][ry] || LEFT[rx+fz[k]][ry]&&RIGHT[rx+fz[k]][ry])
{
if(fy[k]<0 && RIGHT[rx][ry] || fy[k]>0 && LEFT[rx][ry])
{
continue;
}
}
turn(fx[k],fy[k],rx+fz[k],ry,t,path[rx][ry]+1);
}
}
else
{
for(k=8;k<12;k++)
{
if(UP[rx][ry+fz[k]]&&DOWN[rx][ry+fz[k]] || LEFT[rx][ry+fz[k]]&&RIGHT[rx][ry+fz[k]])
{
if(fx[k]<0 && UP[rx][ry] || fx[k]>0 && DOWN[rx][ry])
{
continue;
}
}
turn(fx[k],fy[k],rx,ry+fz[k],t,path[rx][ry]+1);
}
}
}
return -1;
}

int cmpx(int a,int b)
{
return x[a]<x[b];
}

int cmpy(int a,int b)
{
return y[a]<y[b];
}

void discretization()
{
int i,tmp,now;
nn+=2;
for(i=0;i<nn;i++)
{
idx[i]=idy[i]=i;
}
sort(idx,idx+nn,cmpx);
sort(idy,idy+nn,cmpy);

tmp=-1000000000;
now=0;
for(i=0;i<nn;i++)
{
if(x[idx[i]]!=tmp)
{
tmp=x[idx[i]];
now+=2;
}
x[idx[i]]=now;
}
mx=now+2;
tmp=-1000000000;
now=0;
for(i=0;i<nn;i++)
{
if(y[idy[i]]!=tmp)
{
tmp=y[idy[i]];
now+=2;
}
y[idy[i]]=now;
}
my=now+2;
/*
cout<<"离散化结果: "<<endl;
cout<<"x:   "; for(i=0;i<nn;i++) cout<<x[idx[i]]<<" ";cout<<endl;
cout<<"y:   "; for(i=0;i<nn;i++) cout<<y[idy[i]]<<" ";cout<<endl;
*/
nn-=2;
ax=x[nn];
ay=y[nn];
bx=x[nn+1];
by=y[nn+1];
}

void INIT()
{
int i,j,k;
memset(mp,0,sizeof(mp));
memset(path,-1,sizeof(path));
memset(UP,0,sizeof(UP));
memset(DOWN,0,sizeof(DOWN));
memset(LEFT,0,sizeof(LEFT));
memset(RIGHT,0,sizeof(RIGHT));
for(i=0;i<n;i++)
{
for(j=x[i]+1;j<x[i+n];j++)
{
mp[j][y[i]+1]=mp[j][y[i+n]-1]=1;
}
for(j=y[i]+1;j<y[i+n];j++)
{
mp[x[i]+1][j]=mp[x[i+n]-1][j]=1;
}
for(j=x[i];j<=x[i+n];j++)
{
LEFT[j][y[i]]=true;
RIGHT[j][y[i+n]]=true;
}
for(j=y[i];j<=y[i+n];j++)
{
DOWN[x[i]][j]=true;
UP[x[i+n]][j]=true;
}
}
/*
cout<<"打印地图:"<<endl;
for(j=my-1;j>=0;j--)
{
for(i=0;i<mx;i++)
{ // 2表示两点之间有不可走的边, 1表示两点之间有可走的边 , 0表示两点之间无边, .表示整数坐标点
if(i%2==0 && j%2==0) cout<<". ";
else if(i%2==1 && j%2==1) cout<<"  ";
else if(mp[i][j] || UP[i][j]&&DOWN[i][j] || LEFT[i][j]&&RIGHT[i][j]) cout<<"2 ";
else cout<<(UP[i][j]||DOWN[i][j]||LEFT[i][j]||RIGHT[i][j])<<" ";
}
cout<<endl;
}
*/
}

int input()
{
int i;
int X1,X2,Y1,Y2;
scanf("%d%d%d%d",&ax,&ay,&bx,&by);
if(ax==0 && bx==0 && ay==0 && by==0)
{
return 0;
}
scanf("%d",&n);
nn=n+n;
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
x[i]=min(X1,X2);
x[i+n]=max(X1,X2);
y[i]=min(Y1,Y2);
y[i+n]=max(Y1,Y2);
}
x[nn]=ax;
x[nn+1]=bx;
y[nn]=ay;
y[nn+1]=by;
return 1;
}

int main()
{

while(input())
{
discretization();
if(ax==bx && ay==by)
{
puts("0");
continue;
}
INIT();
printf("%d\n",bfs());
/*
cout<<"打印路径:"<<endl;
for(int i=my;i>=0;i--)
{
for(int j=0;j<mx;j++)
{
printf("%3d",path[j][i]);
}
cout<<endl;
}
*/
}
return 0;
}

/*

// 绕路   2
1 1 1 4
1
0 2 2 3

// 直走  0
1 1 1 4
1
3 3 4 5

// 沿着边直走  0
0 1 0 7
2
0 2 2 3
-1 4 0 5

// 沿着边直走  0
0 1 0 7
2
0 2 2 3
0 3 2 4

// 无法穿过缝隙,绕路   2
0 1 0 7
2
0 2 2 3
-1 3 0 5

// 无法到达  -1
0 0 5 5
4
-1 1 1 2
1 -1 2 1
-1 -1 1 -2
-1 1 -2 -1

// 同点经过两次。  5
1 3 4 1
10
-1 -1 3 2
3 -1 7 0
7 -1 11 3
9 3 11 7
-1 7 11 9
0 5 4 7
-1 2 0 7
2 2 4 3
4 3 5 4
5 4 8 6

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