标签:def ++ 开始 解法 show return gif style col
题目大意:在一个已经有障碍的地图上,设置尽可能少的障碍使得(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[1000010]; int step[1000010]; int mmap[1000010]; int _map[1000010]; int que[1000010][2]; int n,m; int suan(int x,int y) { if (x>n || y>m || x<1 || y<1) return 0; return (x-1)*m+y; } void fin(int x,int y) { mmap[suan(x,y)]=1; if( _map[suan(x-1,y)] && !mmap[suan(x-1,y)] ) fin(x-1,y); if( _map[suan(x,y-1)] && !mmap[suan(x,y-1)] ) fin(x,y-1); } int main() { scanf("%d%d",&n,&m);int mmstep=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { step[suan(i,j)]=0; char ch=getchar(); while (ch!=‘.‘ && ch!=‘#‘) ch=getchar(); if (ch==‘.‘) _map[suan(i,j)]=1; else _map[suan(i,j)]=0; } fin(n,m); if (!mmap[suan(1,1)]){printf("0\n");return 0;} int tt=1,ll=0;que[ll][0]=1;que[ll][1]=1; while (ll<tt) { int x=que[ll][0],y=que[ll][1]; int nowtp=step[suan(x,y)];num[nowtp]++; if (nowtp>mmstep) mmstep=nowtp; int tmp=suan(x+1,y); if (x<n && mmap[tmp] && (!step[tmp])) { que[tt][0]=x+1; que[tt][1]=y; step[suan(x+1,y)]=nowtp+1; //printf("%d %d\n",x+1,y); tt++; } tmp=suan(x,y+1); if (y<m && mmap[tmp] && !step[tmp]) { que[tt][0]=x; que[tt][1]=y+1; step[suan(x,y+1)]=nowtp+1; //printf("%d %d\n",x,y+1); tt++; } ll++; } int ans=2; if (mmstep != n+m-2) ans=0; for (int i=1;i<mmstep;i++) if (num[i]<ans) ans=num[i]; printf("%d\n",ans); }
#include <stdio.h> int n,m; bool flag[1000100]; bool tmp=0,tmp2=0; int get(int x,int y) { if (x>n || y>m) return 0; return (x-1)*m+y; } bool fin1(int x,int y) { flag[get(x,y)]=0; if (x==n &&y==m) {tmp=true;return 0;} if (!tmp && flag[get(x+1,y)]) fin1(x+1,y); if (!tmp && flag[get(x,y+1)]) fin1(x,y+1); } bool fin2(int x,int y) { flag[get(x,y)]=0; if (x==n &&y==m) {tmp2=true;return 0;} if (!tmp2 && flag[get(x,y+1)]) fin2(x,y+1); if (!tmp2 && flag[get(x+1,y)]) fin2(x+1,y); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) for (int j=1;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(1,1); if (!tmp){ printf("0\n");return 0; } flag[1]=true;flag[get(n,m)]=true; fin2(1,1); if (tmp2){ printf("2"); } else printf("1"); }
codeforces #583 problem D(搜索好题)
标签:def ++ 开始 解法 show return gif style col
原文地址:https://www.cnblogs.com/askl123/p/11478851.html