第五周小结
一.题型整理
上周总结了搜索的棋盘问题与组合问题,这周继续做题与看博客,又遇到几种题型,在此简单总结一下:
- 排列问题: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.继续寻找不足,强化基础,下周再接再厉。