2022/4/17 周总结

本文回顾了DFS与BFS在解决连通块问题上的应用,如洛谷P1596,探讨了利用分治策略解决南蛮图腾等题目,并揭示了部分题目中的“偷跑”解法。作者计划深化学习分治算法和剪枝优化,重点关注快速排序等典型案例。
摘要由CSDN通过智能技术生成

前言:本周的阅读依然着重于DFS与BFS,同时在阅读与练习的过程中遇到了部分利用分治算法解出的题目,于是阅读了对有关分治的博客,同时也了解了部分利用剪枝进行算法优化的问题。接下来要对剪枝部分进行深入学习。



对于简单的DFS例如:洛谷P1331 海战、洛谷P1451 求细胞数量、洛谷P1596 Lake Counting S,这种连通块的问题,题解方法都是类似的,都只是无非就是在递归搜索的过程中搜索范围的不同。

连通块问题 

以洛谷P1596 Lake Counting S 为代表:

洛谷P1596 [USACO10OCT]Lake Counting S

由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个(1<=N<=100;1<=M<=100)网格图表示。每个网格中有水('W') 或是旱地('.')。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。

输入格式:

第1行:两个空格隔开的整数:N 和 M 第2行到第N+1行:每行M个字符,每个字符是'W'或'.',它们表示网格图中的一排。字符之间没有空格。

无非就是要将判断搜索的范围调制八个,需要创建八个位置坐标去搜索,在搜完之后可以将水坑归零防止重新输入 那么可以很容易写出核心DFS代码

void dfs(int x,int y){
    a[x][y]='.';
    int xx,yy;
    for(int i=-1;i<=1;i++)
    {
        for(int j=-1;j<=1;j++)
        {
            xx=x+i;
            yy=y+j;
            if(xx>=0&&xx<=n&&yy>=0&&yy<m&&a[xx][yy]=='W')
            {
                dfs(xx,yy);
            }
        }
    }
    return;
}

然后在主函数中循环判断即可。

至于p1331海战,其实就是多加了一个不合法的条件,在程序中额外判断一下即可。


题目“偷跑” 

在日常做题和进行比赛的过程中,其实可以发现有部分题目是可以“偷跑” 的,通过题目本身的漏洞也可以找到题目的特殊解,这些解可以满足题目要求的条件,但并不需要进行复杂的算法或是代码呈现。当然,这并不是一种正道,找出这种特殊解除了运气的成分还有思维的活跃度要高。

对于类似洛谷P6183 [USACO10MAR] The Rock Game  S 这种题目就可以先模拟,再发现其规律,利用非DFS的算法实现AC。

这道codeforces中的题目也属于可以“偷跑”的题目,可以发现每一种情况中的解中都有一种形式相近相似的特定解来实现。 


有关分治问题的题目 

 最开始引发我对分治问题的兴趣的是:洛谷P1498 南蛮图腾 这道题,这道题我最先想到的就是这种图形的问题直接暴力模拟就OK,找出图形在行、列的规律直接在主函数中模拟得到最终结果。但是看了题解才发现这种题目是可以使用分治来实现的。

洛谷P1498 南蛮图腾  

题目的输入输出:

 

首先构建题目的基础图形,这道题分治其实就是对于实例输入2 这种情况分成几个小问题:向下复制一个基础图形,向右复制一个,再向上复制一个,最终完成题目输出,对于过程可以打一个巨大的内容为“ ”的矩阵,然后在这个数组中操作就可以。 

小思考 

至于分治,在做题过程中主要的是题目如何正确的分成若干的小的题目,同时这几个小的题目的解决方法也要相近相似,这样可以通过:分解->治理->合并,这几个步骤将一个问题更迅速的解决,另外在分治算法中,因为各个小问题的解题方法是一致的,因而可以使用递归来实现分治。在过去学习的例如快速排序、二分查找就有着分治的影子。

快速排序这种排序就是一种典型的分治,将数组不断二分进行排序

void seq(int a[],int n,int m)
{
    int x=n,y=m,flag=a[(n+m)/2],temp;
    do//实现寻找“标志数”两端第一个大于、小于的数值并进行交换
    {
        while (a[x]<flag)x++;
        while (a[y]>flag)y--;
        if(x<=y)
        {
            swap(a[x],a[y]);
            x++;
            y--;
        }
    }
    while(x<=y);

    if(n<y) seq(a,n,y);//递归调用实现快速排序。
    if(x<m) seq(a,x,m);
}

 


总结:在codeforces的比赛中前几道题似乎并不涉及到多少算法问题,大部分都是模拟问题希望在接下来的。在本次总结中有关分治的题目涉及并不多,在接下来我要总结一下运用分治思想或是算法求解的题目,进行系统的学习。同时对于剪枝优化也要进行深入的学习。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值