2012/12/31 修正。
最主要的修改了拐角点无法通过的问题,将格子分为8种情况特判。例如某个格子的左下,右下,左上的格子都是黑格,那么这个拐角点就是"L"形状的,我设它为状态5。那么在这个格子上,只有上方和右方可以进入格子,而当从右方进入格子时只有上方能离开格子,从上方进入时只有右方能离开。
这些判定通过两个函数check3(格子状态,进入方向)和check2(格子状态,进入方向,离开方向)来判定。
另外小修改了离散化的坐标,将起点终点的坐标也加入离散,这样就可以不用特判ans=0的情况了。
修改后的程序能够通过这组数据了:
0 -1 2 1
3
-1 0 0 1
0 1 1 2
1 -2 3 0
正确答案为1。经过拐角点。
修改后的程序能够在HDUAC了。不过用时还是有点多。。
修正代码如下:
#include
#include
#include
#include
#include
using namespace std;
#define NN 400
#define INF 100000000
int stx,sty,edx,edy;
int n,tx,ty,sx[NN],sy[NN],a,b,c,d,ttx,tty,i,ans,flag;
int dis[NN][NN][5],inq[NN][NN][5],g[NN][NN];
int dx[]={0,1,0,-1};//上 右 下 左
int dy[]={1,0,-1,0};
struct point {
int x,y;
void init(int _x,int _y){x=_x;y=_y;};
}bu[NN][10];
int bsch1(int val,int v[],int l,int r){//二分寻找离散后的位置,其实暴力也可以吧
int mid;
while(l<=r){
mid=(l+r)>>1;
if (v[mid]==val) return mid;
if (v[mid] qx,qy,qd;
for(j=0;j<4;j++){dis[stx][sty][j]=0;qx.push(stx);qy.push(sty);qd.push(j);inq[stx][sty][j]=1;}
while(!qx.empty()){
ux=qx.front();qx.pop();uy=qy.front();qy.pop();ud=qd.front();qd.pop();
inq[ux][uy][ud]=0;
for(dir=0;dir<4;dir++)if (check2(g[ux][uy],ud,dir)){
vx=ux+dx[dir];vy=uy+dy[dir];vd=dir;
if (vx>=1&&vx<=tx&&vy>=1&&vy<=ty&&check3(g[vx][vy],vd)&&dis[vx][vy][vd]>dis[ux][uy][ud]+(ud==vd?0:1)){
dis[vx][vy][vd]=dis[ux][uy][ud]+(ud==vd?0:1);
if (!inq[vx][vy][vd]){
inq[vx][vy][vd]=1;
qx.push(vx);qy.push(vy);qd.push(vd);
}
}
}
}
int ans=INF;
for(j=0;j<4;j++){
if (ans>dis[edx][edy][j]) ans=dis[edx][edy][j];
}
return ans;
}
void add(int a,int b,int c,int d){//将每个坐标自身,+1,-1都加入进行离散
sx[++tx]=a;sx[++tx]=a-1;sx[++tx]=a+1;
sx[++tx]=c;sx[++tx]=c-1;sx[++tx]=c+1;
sy[++ty]=b;sy[++ty]=b-1;sy[++ty]=b+1;
sy[++ty]=d;sy[++ty]=d-1;sy[++ty]=d+1;
}
inline bool cmp1(int x,int y){return x10000000) ans=-1;//我不会告诉你忘记输出-1和不会做是一样的结果的
printf("%d\n",ans);
}
return 0;
}
________________________________________________________________________________________________________________
现场赛被血虐。。太弱了。
#include
#include
#include
#include
#include
using namespace std;
#define NN 400
#define INF 100000000
int stx,sty,edx,edy;
int n,tx,ty,sx[NN],sy[NN],a,b,c,d,ttx,tty,i,ans,flag;
int dis[NN][NN][5],inq[NN][NN][5],g[NN][NN];
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
struct point {
int x,y;
void init(int _x,int _y){x=_x;y=_y;};
}bu[NN][10];
int bsch1(int val,int v[],int l,int r){//二分寻找离散后的位置,其实暴力也可以吧
int mid;
while(l<=r){
mid=(l+r)>>1;
if (v[mid]==val) return mid;
if (v[mid]>1;
if (v[mid]==val) return mid;
if (v[mid]>val) {if (ans>mid) ans=mid;r=mid-1;}
else l=mid+1;
}
return ans;
}
inline void check(int i,int j){ //检查格子是否可走
if (g[i-1][j]&&g[i+1][j]) g[i][j]=1;
if (g[i][j-1]&&g[i][j+1]) g[i][j]=1;
if (g[i-1][j-1]&&g[i+1][j+1]||g[i+1][j-1]&&g[i-1][j+1]) g[i][j]=1;
}
void make_graph(){//建图,将不可行格子涂黑
int i,j,k,tmpx1,tmpx2,tmpy1,tmpy2;
memset(g,0,sizeof(g));
for(i=1;i<=n;i++){
tmpx1=bsch1(bu[i][1].x+1,sx,1,tx);tmpx2=bsch1(bu[i][3].x-1,sx,1,tx);
tmpy1=bsch1(bu[i][1].y+1,sy,1,ty);tmpy2=bsch1(bu[i][3].y-1,sy,1,ty);
for(j=tmpx1;j<=tmpx2;j++)
for(k=tmpy1;k<=tmpy2;k++)
g[j][k]=1;
}
for(i=2;i qx,qy,qd;
for(j=0;j<4;j++){dis[stx][sty][j]=0;qx.push(stx);qy.push(sty);qd.push(j);inq[stx][sty][j]=1;}
while(!qx.empty()){
ux=qx.front();qx.pop();uy=qy.front();qy.pop();ud=qd.front();qd.pop();
inq[ux][uy][ud]=0;
for(dir=0;dir<4;dir++){
vx=ux+dx[dir];vy=uy+dy[dir];vd=dir;
if (vx>=1&&vx<=tx&&vy>=1&&vy<=ty&&g[vx][vy]==0&&dis[vx][vy][vd]>dis[ux][uy][ud]+(ud==vd?0:1)){
dis[vx][vy][vd]=dis[ux][uy][ud]+(ud==vd?0:1);
if (!inq[vx][vy][vd]){
inq[vx][vy][vd]=1;
qx.push(vx);qy.push(vy);qd.push(vd);
}
}
}
}
int ans=INF;
for(j=0;j<4;j++){
if (ans>dis[edx][edy][j]) ans=dis[edx][edy][j];
}
return ans;
}
void add(int a,int b,int c,int d){//将每个坐标自身,+1,-1都加入进行离散
sx[++tx]=a;sx[++tx]=a-1;sx[++tx]=a+1;
sx[++tx]=c;sx[++tx]=c-1;sx[++tx]=c+1;
sy[++ty]=b;sy[++ty]=b-1;sy[++ty]=b+1;
sy[++ty]=d;sy[++ty]=d-1;sy[++ty]=d+1;
}
inline bool cmp1(int x,int y){return x10000000) ans=-1;//我不会告诉你忘记输出-1和不会做是一样的结果的
printf("%d\n",ans);
}
return 0;
}