poj3984周赛E题

一开始看到求最短路径,直接dfs求最短路径(记得返回时要将访问清空还要将增加的步数清空)但是后来看到要输出路径。。。如果要输出路径,而且是最短,那么各个方案的路径都要保存。这感觉似曾相似啊,不就是我昨天素数环多写的。包含数组的结构体。。。现在想想心有余悸。。。果断放弃这种方法。准备去搜题解。。。现在先放一下求最短路径的代码(虽然这道题不可以,但是求最短路径是没毛病的。
注意点:
1.搜索完一个点之后记得要将flag【】=0,ans–(步数清空)
2.在双层for循环模拟判断时,要加一个判断条件(flag【】=0)
举个例子:
这样是可以的

int dfs(int h,int l)
{
    ...
    for(int w=-1;w<=1;w++)
        for(int e=-1;e<=1;e++)
        if((w==0||e==0)&&(e!=0||w!=0)&&flag[h+w][l+e]==0)
        {dfs(h+w,l+e);
        flag[h+w][l+e]=0;}
        ...
}

这样是不行的


int dfs(int h,int l)
{
    ...
    if(flag[h+w][l+e]==1)return ;
    for(int w=-1;w<=1;w++)
        for(int e=-1;e<=1;e++)
        if((w==0||e==0)&&(e!=0||w!=0))
        {dfs(h+w,l+e);
        flag[h+w][l+e]=0;}
        ...
}

显然如果用下面这样那么访问过的也会被重新标记为未访问
模拟前进有两个方式
数组模拟:一般判断条件在准备dfs之前。
使用场合:需要清空访问状态(当然用双层也可以,这是一定注意要将判断访问状态放在下面如上面举例)的时候,像求最短路径什么的。
双层for模拟:判断条件在dfs内最上方,不满足就return(判断条件太多,放在dfs前的话判断太多了)。
使用场合:不需要清空访问状态的时候(连通块,最大能到哪里)用这种很简洁。
不太喜欢用数组模拟前进后退,所以用双层for之前找连通块不需要清空flag所以就没考虑过这个问题,结果一直无限循环,看来以后要学会用一下数组这种方法。
3.小细节。比如说这一次
if((w==0||e==0)&&(e!=0||w!=0)) 不小心写成了if(w==0||e==0&&(e!=0||w!=0))
又无限循环。。。
以上为自己写题的一些思路

接下来看看正确答案
首先是dfs+双端队列(输出路径方法)
看了一下别人的答案https://blog.csdn.net/jingqi814/article/details/12024315(侵权删)
他的基本思路就是向下向右走,分别存入栈中,然后如果不符合,那么就将这个路pop掉从之前的节点继续选择最后找到的第一条路输出来。
由于回溯的时候需要在末尾处理但是输出又要从头开始,所以他用栈但是输出时先赋给向量。
稍微更改了一下,用了双端队列,基本思想跟这个答主是一样的,但是其实这种是有问题的,有可能选择的路不是最短路。然而过了。。。更好的方法不是dfs而是bfs,先把这种思路的代码(ac)放下面等下再放bfs的代码

#include<iostream>//(12.24)
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
int arc[7][7],flag[7][7];
struct node
{
    int h,l;
};
deque<node>a;
int dfs(int h,int l)
{
    if(!flag[h][l])
    {node cur;
    cur.h=h;
    cur.l=l;
    flag[h][l]=1;
    a.push_back(cur);}
    if (h==5&&l==5)return 1;
    if(!flag[h+1][l]&&!arc[h+1][l])dfs(h+1,l);
    else if(!flag[h][l+1]&&!arc[h][l+1])dfs(h,l+1);
    else
    {
        a.pop_back();
        node cur=a.back();
        dfs(cur.h,cur.l);
    }
}
int main()
{
    for(int w=1;w<=5;w++)
    {for(int e=1;e<=5;e++)
    {cin>>arc[w][e];arc[6][e]=1;arc[0][e]=1;}
    arc[w][6]=1;arc[w][0]=1;}
    memset(flag,0,sizeof(flag));
    dfs(1,1);
    while(!a.empty())
    {node cur1=a.front();
    cout<<"("<<cur1.h-1<<", "<<cur1.l-1<<")"<<endl;
    a.pop_front();}
}

猜你喜欢

转载自blog.csdn.net/weixin_43331783/article/details/85140774