PS:这一题也是写了二十多遍了,去年这个时候写的,也是写了几天。过几天等考试结束了,集训的时候重新把几种方法再写一下!
题意:中文题,自行理解。
思路:
- 三维+优先队列写的,跑的时间是最短的,780ms。
- dfs+剪枝+判断方向是否改变。跑了辣么长时间6895ms。
PS:flag标记判断方向就行了。
三维+优先队列写的,跑的时间是最短的,780ms。
//三维+优先队列
#include
#include
#include
using namespace std;
int aaa[1100][1100];
int book[1100][1100][4];
int aa,bb,cc,dd;
int flag;
int n,m;
int dir[4][2]= {{1,0},{0,-1},{0,1},{-1,0}};
struct node
{
int x;
int y;
int step;
int to;
// int qqq;
bool operator < (const node &a)const
{
return a.stepQ;
// queueQ;
p.x=a;
p.y=b;
p.step=0;
p.to=-1;
Q.push(p);
while(!Q.empty())
{
// q=Q.front();
q=Q.top();
Q.pop();
for(int i=0; i<4; i++)
{
p=q;
p.x+=dir[i][0];
p.y+=dir[i][1];
if(p.x>0&&p.x<=n&&p.y>0&&p.y<=m&&(aaa[p.x][p.y]==0||(p.x==cc&&p.y==dd))&&book[p.x][p.y][i]==0)
// if(p.x>0&&p.x<=n&&p.y>0&&p.y<=m&&book[p.x][p.y]==0&&(aaa[p.x][p.y]==0||(p.x==cc&&p.y==dd)))
{
book[p.x][p.y][i]=1;
if(p.to!=i)
{
if(p.step<=2)
{
p.step=q.step+1;
p.to=i;
}
else
continue;
}
else
{
if(p.step<=3)
{
p.step=q.step;
p.to=i;
}
}
if(p.x==cc&&p.y==dd&&p.step<=3)
{
flag=1;
return;
}
Q.push(p);
// Q.push(p);
}
}
}
return ;
}
int main()
{
while(~scanf("%d %d",&n,&m)&&(n+m))
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%d",&aaa[i][j]);
}
}
int ss;
scanf("%d",&ss);
while(ss--)
{
memset(book,0,sizeof(book));
flag=0;
scanf("%d %d %d %d",&aa,&bb,&cc,&dd);
if((aaa[aa][bb]!=aaa[cc][dd])||aaa[aa][bb]==0||aaa[cc][dd]==0)
{
printf("NO\n");
continue;
}
bfs(aa,bb,cc,dd);
if(flag==0)
printf("NO\n");
else
printf("YES\n");
}
}
return 0;
}
dfs+剪枝+判断方向是否改变:
#include
#include
#define inf 0x3f3f3f3f
int a[1100][1100];
int book[1100][1100];
int flag,step,k;
int n,m;
int aa,bb,cc,dd;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int x1,int y1,int to,int step)
{
book[x1][y1]=1;
// if(k)return ;
if(k||step>3)
return ;//这里注意剪枝,否则step如果>3但是不满足下一个if语句的话,会进入下一个for循环,每次循环4次,数据大了会超时
if(x1==cc&&y1==dd)
{
if(step<=3)//因为for循环里面进去的step如果是=3且方向改变的话,step会变成4不满足条件
{
k=1;
return;
}
}
int face;//判断转弯次数
for(int i=0; i<4; i++)
{
int tx=x1+dir[i][0];
int ty=y1+dir[i][1];
if(tx>0&&tx<=n&&ty>0&&ty<=m&&book[tx][ty]==0&&step<=3&&(a[tx][ty]==0||(tx==cc&&ty==dd)))
{
//
face=step;//****
//控制每一次对于同一个点的四个方向搜的时候,原步数不变,否则每一步都在同一个点的上一步++了
if(to!=i)//第一次方向肯定改变,因为需要保证步数++,所以后来满足条件的最大step是3
{
// to=i;//***
face++;
}
else
{
to=to;
step=step;//方向想等的时候转弯次数不变
}
book[tx][ty]=1;
dfs(tx,ty,i,face);//递归不是to,是上次走的那个方向也就是i
//第一次搜的时候第三个位置是to,因为要保证第一个step++
book[tx][ty]=0;//取标
}
}
return;
}
int main()
{
while(~scanf("%d %d",&n,&m)&&(n+m))
{
memset(a,0,sizeof(a));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
scanf("%d",&a[i][j]);
}
int ss;
scanf("%d",&ss);
for(int i=0; i