第五周小结

第五周小结


一.题型整理
  上周总结了搜索的棋盘问题与组合问题,这周继续做题与看博客,又遇到几种题型,在此简单总结一下:

  • 排列问题:N个数按一定规则进行排列,有几种排列方式。

题目链接P1706 全排列问题

题意:输出自然数 1 到 n 所有不重复的排列。

题解:1.分析问题,适合用深搜解决。
2.先定义两组数组,一组用来存放解,一组用来标记。
3.套用深搜模板写一个DFS函数,再写一个print函数进行输出。

代码

#include<bits/stdc++.h>
using namespace std;
int n,b[100],a[100];
void print()
{
    int i;
    for(i=1;i<=n;i++)
    cout<<a[i];
    cout<<endl;
}
void dfs(int k)
{
    int i;
    if(k==n)
    {
        print();
        return;
    }
    for(i=1;i<=n;i++)
    { if(!b[i])
        {   b[i]=1;
            a[k+1]=i;
            dfs(k+1);
            b[i]=0;//回溯
        }
    }
}
int main()
{   cin>>n;
    dfs(0);
    return 0;
}
  • 连通性问题

题目链接P1141 01迷宫.

题意:给定一个仅由数字0与1组成的n×n格迷宫,若你位于一格0上,那你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上,问从某一格开始能移动到多少个格子(包含自身)。

题解:1.用深搜法,定义两个数组,一组用来存放地图,一组用来标记。
2.记录每个格子是否被搜过,如果这格没搜过就从这个格子开始搜。
3.每搜到一个格子解的个数加1,数组记录当前格子位置,每次都向4个方向的满足条件的格子扩展。
4.注意要检查是否越界。

代码

#include<bits/stdc++.h>
using namespace std;
int n,t;
int s[1010][1010];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int a[1010][1010];
void dfs(int x, int y)
{  if(x>n||x<1||y>n||y<1||a[x][y]>-1) return;
    t++;
    a[x][y]=0;
    for(int i=0;i<4;i++)
   { if(s[x+dx[i]][y+dy[i]]!=s[x][y])
      dfs(x+dx[i], y+dy[i]);
    }
}
int main()
{  int m;
    cin>>n>>m;
     memset(a,-1,sizeof(a));
    for(int i=1;i<=n;i++)
    { char c[1010];
      cin>>c;
      for(int j =1;j<=n;j++)
    {s[i][j]=c[j-1]-48;}
    }
    for(int i=1;i<=m;i++)
    {  int x, y;
       t=0;
       cin>>x>>y;
        dfs(x, y);
        cout<<t;
        memset(a,-1,sizeof(a));
    }
}

二.几点新收获

1.freopen函数
  freopen是一个非常好用的文件输入输出的函数,使用freopen函数可以解决测试数据的输入问题,避免重复输入,节省了输入数据的时间。

在 stdio.h文件下使用
freopen(“文件名.in”,“r”,stdin);
freopen(“文件名.out”,“w”,stdout);

2.return的使用
  在解决一些只需输出其中一个解就结束的问题时,可以通过return来结束程序。return的功能是结束一个方法,当一个方法执行到一个return语句时这个方法将被结束。
   用continue和break也可以实现,但不如return便捷。其区别在于continue结束当前循环,break结束整个循环,而return直接结束整个程序,不管这个return处于多少层循环之中。

3.memset函数的使用
   在看洛谷的题解时经常看到memset函数,于是大体了解了下他的用法。
   memset是一个初始化函数,作用是将某一块内存空间设置为指定的值。可以用于为数组赋值或清空数组。

void *memset(void *s, int c, int n);
s为指针或数组;
c是要被设置的值;
n是s的长度;
返回类型是一个指向存储区s的指针。

注意不能用它将int数组出初始化为0和-1之外的其他值。

4.set去重
  在解决去重问题时,可以使用STL中的set。
  set中的元素都是排好序的;set集合中没有重复的元素。

begin()  返回set容器第一个元素的迭代器
end()      返回一个指向当前set末尾元素的下一位置的迭代器.
clear()    删除set容器中的所有的元素
empty()     判断set容器是否为空
max_size()   返回set容器可能包含的元素最大个数
size()      返回当前set容器中的元素个数
rbegin()    返回的值和end()相同
rend()     返回的值和begin()相同

三.心得
1.需要加大看题练题力度,遇到的不懂的地方一定要及时解决,不留存疑。
2.看到不明白的代码,可以将整个过程在脑中运行一遍,争取每一步都理顺理解。看到好的解法,要好好理解体会,为什么人家会这么写,他是怎么想到的,学习他的思路,将其化为自己的知识。
3.继续寻找不足,强化基础,下周再接再厉。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值