2017/8/3训练日记(DFS&&Codeforces Round #418 (Div. 2))

上午看了下dfs顺便在杭电a了两道dfs的题,下午做的cf的练习,感觉自己好菜啊!

 * DFS核心伪代码 
 * 前置条件是visit数组全部设置成false 
 * @param n 当前开始搜索的节点 
 * @param d 当前到达的深度 
 * @return 是否有解 

bool DFS(Node n, int d)

{  

    if (isEnd(n, d)){//一旦搜索深度到达一个结束状态,就返回true  
        return true;  
    }  
  
    for (Node nextNode in n){//遍历n相邻的节点nextNode  
        if (!visit[nextNode]){//  
            visit[nextNode] = true;//在下一步搜索中,nextNode不能再次出现  
            if (DFS(nextNode, d+1)){//如果搜索出有解  
                //做些其他事情,例如记录结果深度等  
                return true;  
            }  
  
            //重新设置成false,因为它有可能出现在下一次搜索的别的路径中  
            visit[nextNode] = false;  
        }  
    }  
    return false;//本次搜索无解  

}  //类似于眼镜掉到了地上,我们首先选定一个方向去找,直到最后或找个眼镜结束,再找不到就换方向从头开始找

在我们遇到的一些问题当中,有些问题我们不能够确切的找出数学模型,即找不出一种直接求解的方法,解决这一类问题,我们一般采用搜索的方法解决。

搜索就是用问题的所有可能去试探,按照一定的顺序、规则,不断去试探,直到找到问题的解,试完了也没有找到解,那就是无解,试探时一定要试探完所有的情况

深度优先搜索用一个数组存放产生的所有状态。
(1) 把初始状态放入数组中,设为当前状态;
(2) 扩展当前的状态,产生一个新的状态放入数组中,同时把新产生的状态设为当前状态;
(3) 判断当前状态是否和前面的重复,如果重复则回到上一个状态,产生它的另一状态;
(4) 判断当前状态是否为目标状态,如果是目标,则找到一个解答,结束算法。
(5) 如果数组为空,说明无解。

http://www.cnblogs.com/whywhy/p/4888632.html

http://blog.csdn.net/ns_code/article/details/19617187

上面是dfs的核心内容,主要的还是要看大佬们的博客再加上做题为主;

下面写一下Codeforces Round #418 (Div. 2)的大部分题解

下午两个半小时做出两个题来,菜哭,主要是毁在题意的分析上了,题意弄错了,第二题怎么都过不去

第一题很简单

题意:将b数组的数插入a中为0的地方。如果可以不构成递增序列输出Yes,否则输出No。 
题解:将b数组降序插入a中,判断即可。 

第二题

题意 :给两个n个数的排列a和b 保证两个排列至少有一个i使ai!=bi 求一个排列p使得对于a和b均满足存在一个数j使得ai!=pi bj!=pj。 
题解:分析出a,b数组最多有两个不一样的位置。然后暴力判断即可。 

哎这个题要不是英语不好一开始题意理解错了早就a了,说的是a和b均满足存在一个数,而开始读题的时候并没又看到这个条件所以错了

第三题

题意:给你一个长度为n的字符串。q次询问,每次询问在最多修改m次的前提下,能构成连续ci的长度。 
题解:尺取法。 (形如蚯蚓的爬动QAQ)

关于尺取法过段时间再详细的看一看

返回的推进区间开头和结尾,求满足条件的最小区间的方法称为尺取法。

1.初始化左右端点


2.不断扩大右端点,直到满足条件


3.如果第二步中无法满足条件,则终止,否则更新结果


4.将左端点扩大1,然后回到第二步

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
const int mod=1e7+9;
int i,j,n,m,k,mx,x,y,l,r,b;
char c,s[2000];
int main()
{
    scanf("%d",&n);
    scanf("%s",s+1);
    scanf("%d",&m);
    for (i=1;i<=m;i++)
    {
        scanf("%d %c",&b,&c);
        mx=0; l=1; k=0;
        for (r=1;r<=n;r++)
        {
            if (s[r]!=c) k++;
            while (k>b) 
            { 
                if (s[l]!=c) k--;
                l++;
            }
            mx=max(mx,r-l+1);
        }
        cout<<mx<<endl;
    }
}

第四题

题意:有很多人跳舞,跳舞范围是个圆,然后跳舞的人分上半夜和下半夜,同一个圈圈里面的人不能同时跳。让你把所有能跳圈圈的面积加起来,得到的面积最大。

贪心就好。把所有圈圈被覆盖的次数统计一下,最大那个肯定加,然后奇数大的加进去,偶数大的减掉,最大的可以在上半夜跳,然后奇数大的在下半夜跳,这就是第一个样例 
英语是硬伤 
No two ranges’ borders have more than one common point, 
这句话告诉我们,没有多于一个的公共点,那就是相嵌了
判断两圆相交条件,圆心距小于两圆半径之和 
所以 ans=s(1)+s(2)-s(3)+s(4)-s(5)+…

第五题

http://blog.csdn.net/marco_l_t/article/details/72910172

dp+dfs+组合数学QAQ看起来好难啊,直接附上大佬的博客吧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值