题目大意:在一个已经有障碍的地图上,设置尽可能少的障碍使得(1,1)无法到达(n,m),行进路线位向下或向右。
数据范围:n*m<=1e6
解题思路:答案一定是小于等于2的,因为可以直接阻碍(1,2)或是(2,1)。首先是自己的错误思路,从(1,1)开始宽搜,若某一相同步数的格子只有一个,那么就可以只阻碍这一个格子从而使之无法抵达(n,m)。但是在比赛结束5min发现了问题:可能存在“能到达(n,m)的相同步数”的格子只有一个,但可能对应这一步数存在另一个无法到达(n,m)的格子扰乱答案。于是就有了题解中的解决方案:先从(n,m)开始深搜,仅标记出能到达(n,m)的网格,再进行我原本的错误思路就可以解决问题。
赛后看评论,有一个更简单的想法,直接两次深搜,其中一个深搜是下的优先级大于右,另一个深搜是右的优先级大于下。这样如果两个路径是不相交的,那么答案为2,两条路径有相交,答案为1。我对这一解法的理解是:前一深搜描绘了可能路线的坐下边界,后一深搜描绘了可能路线的右上边界,两边界不相交那么就有多种方案。
解题代码:
#include <stdio.h> int num[];
int step[];
int mmap[];
int _map[];
int que[][];
int n,m;
int suan(int x,int y)
{
if (x>n || y>m || x< || y<) return ;
return (x-)*m+y;
}
void fin(int x,int y)
{
mmap[suan(x,y)]=;
if( _map[suan(x-,y)] && !mmap[suan(x-,y)] ) fin(x-,y);
if( _map[suan(x,y-)] && !mmap[suan(x,y-)] ) fin(x,y-);
} int main()
{
scanf("%d%d",&n,&m);int mmstep=; for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
step[suan(i,j)]=;
char ch=getchar();
while (ch!='.' && ch!='#') ch=getchar();
if (ch=='.') _map[suan(i,j)]=;
else _map[suan(i,j)]=;
}
fin(n,m);
if (!mmap[suan(,)]){printf("0\n");return ;} int tt=,ll=;que[ll][]=;que[ll][]=;
while (ll<tt)
{
int x=que[ll][],y=que[ll][]; int nowtp=step[suan(x,y)];num[nowtp]++; if (nowtp>mmstep) mmstep=nowtp;
int tmp=suan(x+,y);
if (x<n && mmap[tmp] && (!step[tmp]))
{
que[tt][]=x+;
que[tt][]=y;
step[suan(x+,y)]=nowtp+;
//printf("%d %d\n",x+1,y);
tt++;
}
tmp=suan(x,y+);
if (y<m && mmap[tmp] && !step[tmp])
{
que[tt][]=x;
que[tt][]=y+;
step[suan(x,y+)]=nowtp+;
//printf("%d %d\n",x,y+1);
tt++;
}
ll++;
}
int ans=;
if (mmstep != n+m-)
ans=; for (int i=;i<mmstep;i++)
if (num[i]<ans)
ans=num[i];
printf("%d\n",ans); }
#include <stdio.h>
int n,m;
bool flag[];
bool tmp=,tmp2=;
int get(int x,int y)
{
if (x>n || y>m) return ;
return (x-)*m+y;
}
bool fin1(int x,int y)
{
flag[get(x,y)]=;
if (x==n &&y==m) {tmp=true;return ;}
if (!tmp && flag[get(x+,y)]) fin1(x+,y);
if (!tmp && flag[get(x,y+)]) fin1(x,y+);
}
bool fin2(int x,int y)
{
flag[get(x,y)]=;
if (x==n &&y==m) {tmp2=true;return ;}
if (!tmp2 && flag[get(x,y+)]) fin2(x,y+);
if (!tmp2 && flag[get(x+,y)]) fin2(x+,y);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
char ch=getchar();
while (ch!='.'&& ch!='#') ch=getchar();
if (ch=='.') flag[get(i,j)]=true;
else flag[get(i,j)]=false;
} fin1(,);
if (!tmp){
printf("0\n");return ;
}
flag[]=true;flag[get(n,m)]=true;
fin2(,);
if (tmp2){
printf("");
}
else
printf("");
}