算法作业第三周(leetcode)——675. Cut Off Trees for Golf Event

这题虽然是hard难度,但是其实比前两周的简单很多。下面给出题目地址:

                                https://leetcode.com/problems/cut-off-trees-for-golf-event/description/

本题是一道砍树题。给出一个n*m的矩阵(不大于50*50),矩阵中值为0的数被视为障碍,不能到达或通过。矩阵中值为1的数视为平地,可以通过。大于1的视为树,可以通过。我们的任务就是找一条最短的路径按树的高度从小到大砍掉树,并返回路径长度。其中树被砍掉后就视为草地(其实就是平地)。

本题的想法比较简单,既然要从小到大砍树,那么首先需要把所有树找出来排序(否则找路径时还要全部遍历一遍排大小),这里直接使用set<int>进行排序。然后用bfs计算从前一棵树到后一棵树的最短路径,并将它们累加起来。

下面给上第一次提交的代码:

class Solution {
public:
    set<int> trees;
    list<int> bfs1;
    list<int> bfs2;
    list<int> bfs3;
    int vis[51][51];
    int cutOffTree(vector<vector<int>>& forest) {
        int movx[4]={-1,0,1,0};
        int movy[4]={0,-1,0,1};
        int i,j,lx,ly,step=0,tempx,tempy,temps;
        for(i=0;i<forest.size();i++)
        {
            for(j=0;j<forest[i].size();j++)
            {
                if(forest[i][j]>1)
                    trees.insert(forest[i][j]);
            }
        }
        lx=ly=0;
        for(set<int>::iterator it=trees.begin();it!=trees.end();it++)
        {
            memset(vis,0,sizeof(vis));
            bfs1.push_back(lx);
            bfs2.push_back(ly);
            bfs3.push_back(0);
            while(!bfs1.empty())
            {
                tempx=bfs1.front();
                tempy=bfs2.front();
                temps=bfs3.front();
                bfs1.pop_front();
                bfs2.pop_front();
                bfs3.pop_front();
                if(forest[tempy][tempx]==*it)
                    break;
                for(i=0;i<4;i++)
                {
                    if(tempx+movx[i]>=0&&tempx+movx[i]<forest[0].size())
                    {
                        if(tempy+movy[i]>=0&&tempy+movy[i]<forest.size())
                        {
                            if(!vis[tempy+movy[i]][tempx+movx[i]]&&forest[tempy+movy[i]][tempx+movx[i]]!=0)
                            {
                                bfs1.push_back(tempx+movx[i]);
                                bfs2.push_back(tempy+movy[i]);
                                bfs3.push_back(temps+1);
                                vis[tempy+movy[i]][tempx+movx[i]]=1;
                            }
                        }
                    }
                }
            }
            if(forest[tempy][tempx]!=*it)
                return -1;
            step+=temps;
            bfs1.clear();
            bfs2.clear();
            bfs3.clear();
            lx=tempx;
            ly=tempy;
        }
        return step;
    }
};

花了960ms,只打败了12%的人,有一些慢。

于是做了一些优化,开始发现每一次用bfs都要用memset重置vis数组,所以保存用bfs的次数j,用vis[x][y]=j来表示节点被第j次bfs访问过了,这就省下了memset的时间。

class Solution {
public:
    set<int> trees;
    list<int> bfs1;
    list<int> bfs2;
    list<int> bfs3;
    int vis[51][51];
    int cutOffTree(vector<vector<int>>& forest) {
        int movx[4]={-1,0,1,0};
        int movy[4]={0,-1,0,1};
        int i,j,lx,ly,step=0,tempx,tempy,temps;
        for(i=0;i<forest.size();i++)
        {
            for(j=0;j<forest[i].size();j++)
            {
                if(forest[i][j]>1)
                    trees.insert(forest[i][j]);
            }
        }
        lx=ly=0;
        j=1;
        for(set<int>::iterator it=trees.begin();it!=trees.end();it++)
        {
            bfs1.push_back(lx);
            bfs2.push_back(ly);
            bfs3.push_back(0);
            while(!bfs1.empty())
            {
                tempx=bfs1.front();
                tempy=bfs2.front();
                temps=bfs3.front();
                bfs1.pop_front();
                bfs2.pop_front();
                bfs3.pop_front();
                if(forest[tempy][tempx]==*it)
                    break;
                for(i=0;i<4;i++)
                {
                    if(tempx+movx[i]>=0&&tempx+movx[i]<forest[0].size())
                    {
                        if(tempy+movy[i]>=0&&tempy+movy[i]<forest.size())
                        {
                            if(vis[tempy+movy[i]][tempx+movx[i]]!=j&&forest[tempy+movy[i]][tempx+movx[i]]!=0)
                            {
                                bfs1.push_back(tempx+movx[i]);
                                bfs2.push_back(tempy+movy[i]);
                                bfs3.push_back(temps+1);
                                vis[tempy+movy[i]][tempx+movx[i]]=j;
                            }
                        }
                    }
                }
            }
            if(forest[tempy][tempx]!=*it)
                return -1;
            step+=temps;
            bfs1.clear();
            bfs2.clear();
            bfs3.clear();
            lx=tempx;
            ly=tempy;
            j++;
        }
        return step;
    }
};

花了588ms,可以看到比上一次提交快了一些,但还是比较慢 

然后再想办法优化,一开始认为是set排序速度很慢,于是用数组保存,然后用sort方法排序,结果花了1388ms,慢了好多,于是改了回来 。

然后想可能是用三个队列保存x,y和步长s比较慢,使用一个队列和结构体可能会快一点,然后做了一个结构体。

class Solution {
public:
    struct node{
        int x,y,step;
    };
    set<int> trees;
    list<node> bfs1;
    int vis[51][51];
    int cutOffTree(vector<vector<int>>& forest) {
        int movx[4]={-1,0,1,0};
        int movy[4]={0,-1,0,1};
        int i,j,lx,ly,step=0;
        node temp;
        for(i=0;i<forest.size();i++)
        {
            for(j=0;j<forest[i].size();j++)
            {
                if(forest[i][j]>1)
                    trees.insert(forest[i][j]);
            }
        }
        lx=ly=0;
        j=1;
        for(set<int>::iterator it=trees.begin();it!=trees.end();it++)
        {
            node n;
            n.x=lx;
            n.y=ly;
            n.step=0;
            bfs1.push_back(n);;
            while(!bfs1.empty())
            {
                temp=bfs1.front();
                bfs1.pop_front();
                if(forest[temp.y][temp.x]==*it)
                    break;
                for(i=0;i<4;i++)
                {
                    if(temp.x+movx[i]>=0&&temp.x+movx[i]<forest[0].size())
                    {
                        if(temp.y+movy[i]>=0&&temp.y+movy[i]<forest.size())
                        {
                            if(vis[temp.y+movy[i]][temp.x+movx[i]]!=j&&forest[temp.y+movy[i]][temp.x+movx[i]]!=0)
                            {
                                n.x=temp.x+movx[i];
                                n.y=temp.y+movy[i];
                                n.step=temp.step+1;
                                bfs1.push_back(n);
                                vis[temp.y+movy[i]][temp.x+movx[i]]=j;
                            }
                        }
                    }
                }
            }
            if(forest[temp.y][temp.x]!=*it)
                return -1;
            step+=temp.step;
            bfs1.clear();
            lx=temp.x;
            ly=temp.y;
            j++;
        }
        return step;
    }
};

436ms,看来确实是快了一点,但是还不明显。 

最后想到可能queue内部是用数组实现的,比list快。然而我之所以不用queue是因为它没有clear函数,每一次都要重新声明。于是改成了queue试一下。 

class Solution {
public:
    struct node{
        int x,y,step;
    };
    set<int> trees;
    int vis[51][51];
    int cutOffTree(vector<vector<int>>& forest) {
        int movx[4]={-1,0,1,0};
        int movy[4]={0,-1,0,1};
        int i,j,lx,ly,step=0;
        node temp;
        for(i=0;i<forest.size();i++)
        {
            for(j=0;j<forest[i].size();j++)
            {
                if(forest[i][j]>1)
                    trees.insert(forest[i][j]);
            }
        }
        lx=ly=0;
        j=1;
        for(set<int>::iterator it=trees.begin();it!=trees.end();it++)
        {
            queue<node> bfs1;
            node n;
            n.x=lx;
            n.y=ly;
            n.step=0;
            bfs1.push(n);;
            while(!bfs1.empty())
            {
                temp=bfs1.front();
                bfs1.pop();
                if(forest[temp.y][temp.x]==*it)
                    break;
                for(i=0;i<4;i++)
                {
                    if(temp.x+movx[i]>=0&&temp.x+movx[i]<forest[0].size())
                    {
                        if(temp.y+movy[i]>=0&&temp.y+movy[i]<forest.size())
                        {
                            if(vis[temp.y+movy[i]][temp.x+movx[i]]!=j&&forest[temp.y+movy[i]][temp.x+movx[i]]!=0)
                            {
                                n.x=temp.x+movx[i];
                                n.y=temp.y+movy[i];
                                n.step=temp.step+1;
                                bfs1.push(n);
                                vis[temp.y+movy[i]][temp.x+movx[i]]=j;
                            }
                        }
                    }
                }
            }
            if(forest[temp.y][temp.x]!=*it)
                return -1;
            step+=temp.step;
            lx=temp.x;
            ly=temp.y;
            j++;
        }
        return step;
    }
};

还可以,花了248ms,速度终于不错了。

 可能将queue用自己写的数组实现还能再快一点,但是queue的速度已经比较不错了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值