codeforces #583 problem D(搜索好题)

Posted askl123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces #583 problem D(搜索好题)相关的知识,希望对你有一定的参考价值。

  题目大意:在一个已经有障碍的地图上,设置尽可能少的障碍使得(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
");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
",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
",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
",ans);


}
View Code
技术图片
#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
");return 0;
    }
    flag[1]=true;flag[get(n,m)]=true;
    fin2(1,1);
    if (tmp2){
        printf("2");
    }
    else
        printf("1");
}
View Code

 

以上是关于codeforces #583 problem D(搜索好题)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises)

CodeForces - 583D Once Again... LIS 循环

Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises)

http://codeforces.com/problemset/problem/712/D

http://codeforces.com/problemset/problem/545/D

codeforces 1288D. Minimax Problem(二分)