IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 算法竞赛入门到进阶 读书笔记(2) -> 正文阅读

[数据结构与算法]算法竞赛入门到进阶 读书笔记(2)

一、递归
递归是将大问题逐步缩小为最小的同类问题的过程,即n->n-1…->1,一个递归函数直接调用自己就实现了程序的复用。
全排列:
1.用stl输出全排列
next_peimutation()可以不断生成下一个排列,通常由sort排序得到最小序列后不断用next_permutation()生成下一个字典序更大的排列

sort(a,a+4);
do{  for(i=0;i<4;i++)
{ cout<<a[i]<<" ";
cout<<endl;
} while(next_permutation(a,a+4));

2.递归求全排列
全排列个数就是n!,通过1,2,3…n数字之间的不断交换生成不同排列

int digui(int begin,int end){
if(begin==end)
m++;
else { for(i=begin;i<=end;i++)
{ swap(d[begin],d[i]);
 digui(begin+1,end);
 swap(d[begin],d[i]);}
 }
 }

通过递归依次交换数字产生的每一种分选择都会走向begin==end,记录下总的选择数,即n!。当总数和排列数不同时,其实不难发现,在else中每交换一次,下一次递归begin就加一。所以if中的条件其实就是求排列的数字数,比如说打印10个数中任意三个数的排列,只要让begin ==3就可以计算出一种三个数排列的情况,因此只要修改end即可。
二、子集生成
子集内部的元素是没有顺序的,因此不能当成全排列来做,但是通过书上的讲解,使用二进制进行对照十分方便理解。
将每个子集对应一个二进制数,1对应子集中的某个元素,例如{0,1,2}中的{2}对应的二进制码是100,{1,2}是110,存在一个元素即对应一个1。
组合:
打印所有子集,通过二进制可知子集的数量是2的n次方,用i的循环依次检索0-1<<n范围的二进制码和0-n的j的循环,通过位与判断,存在1则说明有元素重合,将j打印出来即是所有子集。

void zuhe(int n){
for(int i=0;i<(1<<n);i++)
{ for(j=0;j<n;j++)
{ if(i&(1<<j)) cout<<j<<" ";
cout<<endl;}
}
}

当n总数和需要组合的数m不同时,可以使用

k=k&(k-1);

它能够依次消除二进制中的1,通过这个操作即可判断二进制循环i中满足组合数m的情况,然后判断输出子集。

三、广度优先搜索
搜索分为广度优先搜索和深度优先搜索。广度优先搜索即将每层完全探索完后开始探索下一层,但是编译器是单机顺序运行,因此每一层并行计算其实也有顺序。广度优先搜索大多和队列挂钩。
1.hdu 1312 红黑砖块问题
计算能走过的所有砖块数即可用广度优先搜索,将左上右下作为行走方向依次进队和出队,计算所有可走砖块数量。

while(!q.empty())  //经过队列的循环可以检索所有搜索情况
{ start=q.front();
q.pop();
for(i=0;i<4;i++)
{ next.x=start.x+dir[i][0];
  next.y=start.y+dir[i][1];
  //判断next是否在所给范围和可走范围中
  //进队后表示已经走过,不能再走
  num++;
  q.push(next);
  }

2、八数码问题(状态图搜索)
搜索的情况不仅可以看成是数,也可以整体看作一个状态。给出一个三乘三的棋盘,要求求出将初始棋局移动到目标棋局的最小移动数。
广度优先搜索很适合处理最短路程问题,但是搜索状态需要进行对相同状态的去重,即用到康托函数。
康托函数可以计算出一组数所有排列方式的康托值,康托值即给定排列方式在全排列中是第几大排列,计算方法为从首位开始依次计算所有首位小于给定排列方式的排列数。
计算公式为X=a[n]*(n-1)!+a[n-1] *(n-2)!+…+a[2]*1!+a[1]*0!。
a[i]表示原数的第i位在当前未出现的元素中排在第几个

bool Cantor(int str[],int n) //康托函数,str【】为给定的状态
{ long result=0;
 for(int i=0;i<n;i++)
 { int counted=0;
  for(int j=i+1;j<n;j++){
  if(str[i]>str[j])   //判断当前未出现的元素排在第几个,即公式中的a[i]
   ++counted;}
   result+=counted*factory[n-i-1];
   }
   if(!visited[result]){
    visited[result]=1; //如果未重复则记下其使用过,然后使函数返回值为1,即可继续搜索。
    result 1;
    }
    else 
    return 0;
    }

有了判断是否重合的康托函数后即可大大减少复杂度,然后按照红黑砖块的方法依次往下进行广度优先搜索即可。
3 .A * 算法
在求解最短路径问题时往往并不需要像红黑砖块一样进行全面的广度优先搜索,A*算法即BFS+贪心算法。根据曼哈顿距离两点之间最短距离即其实际距离(横坐标距离和纵坐标距离之和),因此这样就不用搜索全部的点。
4.双向广搜
双向广搜即从初始位置和结束位置同时出发进行广度优先搜索,在需要满足知道起点和终点的情况下,使用双向广搜效率会高很多。
双向广搜同样可以解决八数码问题。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-24 11:44:57  更:2021-07-24 11:45:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:21:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码