深度优先搜索

这一个星期我刚开始入门学习搜索,搜索分为深度搜索和广度搜索,但我仅仅只是对深度搜索有一定深度的认识,并做了一部分题,对广度搜索只停留在知识层面的理解,还没做对应的题目。

1、插入一个小题目,不涉及搜索Problem - A - Codeforces

题目的大意是从(0.0)移动一个芯片到给定的点,移动过程中需保证sqrt(pow(x1-x2,2)+pow(y1-y2,2))为整数,求从原点到给定点最少操作次数。

思路:就分为三种情况(1)、给定点为原点:需移动零步;(2)、给定点(x,y)且sqrt(pow(x,2)+pow(y,2))为整数;(3)、其他情况则只需要两步,即沿着x轴和y轴移动。

#include<bits/stdc++.h>
using namespace std;
double s(int x1,int y1,int x2,int y2){
     return sqrt(pow((x1-x2),2)+pow((y2-y1),2));
}
int main(){
    int n,a,b;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a>>b;
        if(a==0&&b==0) {cout<<0;continue;}
        else if(!a&&b!=0||a!=0&&!b||ceil(s(a,b,0,0))==s(a,b,0,0)) {cout<<1;continue;}
        else cout<<2;
}
return 0;}

2、四阶数独

这道题是我接触搜索的第一道题,这题可以说对于一个星期的我来说真的是太难了,整整两天想各种办法,去了解搜索,终于在某一瞬间真正可以看懂这题,并把它写出来。

大意:有一个4*4的格子,每个格子只能填1到4的整数,每行、每列和四等分更小的正方形部分都刚好由1到4组成。

思路:思路就是正常dfs,但是最难理解的地方就是函数dfs中下面的代码了,那时候咋想咋也不懂,再好好想想才知道,这下面的代码是为了标记行、列和四等分,行、列和四等分要保证二维数组的第一项是一样的,这样搜索过程中才能检测数据是否被用过。

int row=(x-1)/4+1;
int col=(x-1)%4+1;
int block=(row-1)/2*2+(col-1)/2+1;

3、[USACO1.5]八皇后 Checker Challenge - 洛谷

这是一道搜索回溯题,和上面题思路差不多,当时做的时候困难在于如何寻找和上面题一样的,各关联位置的如何保证关联,看了课本之后,才明白斜行类型之一的横坐标和纵坐标相加是定值,另一个类型是横坐标加纵坐标相减是一个定值,为防止数组下标为负值故加上一个常数,还有这个其中行(列)不需要判断,因为让a[x]=i,就保证了行(列)不会重复添加。

for(int i=1;i<=n;i++){
  if(!b1[i]&&!b2[x+i]&&!b3[x-i+13])
     a[x]=i;
   b1[i]=1;b2[x+i]=1;b3[x-i+13]=1;
   dfs(x+1);
  b1[i]=0;b2[x+i]=0;b3[x-i+13]=0;}

做2,3题让我懂得

(1)、二维数组:要在一行或一列添加一定限定范围的数时使用;

(2)、一维数组:在要填的所有空里按一定顺序填充时使用;

(3)、dfs可以对集合排序;

(3)、dfs因为里面for的设定可以对其进行字典序输出,改变for也可逆字典序输出;

4、kkksc03考前临时抱佛脚 - 洛谷

这道题唯一的改变在于,dfs中没有用到for循环,只是有个判断条件,这样可以对数据进行处理,

思路:这题虽然不需要像上面两个题一样,找数组相对应的关系,但这题解答的关键在于要想到找两组分别的耗时总和最为接近,dfs对集合里元素进行加法处理,下面这个是我第一遍写的错误代码。

#include<bits/stdc++.h>
using namespace std;
int nowtime,sum,maxtime;
int ans,maxdeep,a[30],s[5];
void dfs(int x);
int main(){
    cin>>s[1]>>s[2]>>s[3]>>s[4];
    for(int i=1;i<=4;i++){
        maxdeep=s[i];
        nowtime=0;
        for(int j=1;j<=s[i];j++)
            cin>>a[j],sum+=a[j];
        dfs(1);
        ans+=sum-nowtime;
        sum=0;
    }
    cout<<ans;
    return 0;
}
void dfs(int x){
     if(x>maxdeep)
            return;
     if(nowtime+a[x]<=sum/2){
        nowtime+=a[x];
        dfs(x+1);
        nowtime-=a[x];
     }
     dfs(x+1);
}

一眼就看出的错误,只怪当时对dfs理解还不到位。

下面是正确的代码。

#include<bits/stdc++.h>
using namespace std;
int nowtime,sum,maxtime;
int ans,maxdeep,a[30],s[5];
void dfs(int x);
int main(){
    cin>>s[1]>>s[2]>>s[3]>>s[4];
    for(int i=1;i<=4;i++){
        maxdeep=s[i];
        nowtime=0;
        maxtime=0;
        for(int j=1;j<=s[i];j++)
            cin>>a[j],sum+=a[j];
        dfs(1);
        ans+=sum-maxtime;
        sum=0;
    }
    cout<<ans;
    return 0;
}
void dfs(int x){
     if(x>maxdeep){
            maxtime=max(maxtime,nowtime);
            return;}
     if(nowtime+a[x]<=sum/2){
        nowtime+=a[x];
        dfs(x+1);
        nowtime-=a[x];
     }
     dfs(x+1);
}

通过这个星期的学习,学的内容真的是太少了,仅仅只是看了一个深度搜索,对新内容学习对我来说接受起来非常困难,这个缺陷是我当前最需要克服的一个困难。希望在以后能通过多看文章,来改善这个缺陷。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值