递推与递归的简单应用

  • 常见的枚举形式
  • 实现指数型枚举
    • DFS (一)
    • DFS (二)
    • 位运算(一)
    • 位运算(二)
  • 实现组合型枚举
    • DFS + 剪枝
  • 实现排列型枚举
    • DFS
  • 费解的开关
  • 奇怪的汉诺塔
  • 分形之城

常见的枚举形式

枚举形式 一般的遍历方法
多项式 循环,递推
指数 递归,位运算
排列 递归 ,c++ next_permutation
组合 递归+剪枝

实现指数型枚举

DFS (一)

思路是沿路径递增的形式输出。

#include <iostream>
#include <stdio.h>
#include <cstring>using namespace std;int n;
int path[100000];void dfs(int stp, int k) {for (int i = 0; i < k; ++i)printf("%d ", path[i]);putchar('\n');if (stp > n)return ;for (int i = stp; i <= n; ++i) {path[k++] = i; //选择dfs(i + 1, k); k -- ; //回溯,不选择}
}int  main() {scanf("%d", &n);dfs(1, 0);return 0;
}

DFS (二)

void calc(int x){if(x == n+1){for(int i =0;i<chosen.size();++i)printf("%d ",chosen[i]);putchar('\n');return ;}//两种选择calc(x+1); //不选chosen.push_back(x); // 选calc(x+1);chosen.pop_back(); // 回溯
}

位运算(一)

// 每一个数都有选与不选两种可能,所以是2的n次方种
for (int i = 0; i < (1 << n); ++i) { for (int j = 0; j < n; ++j)if ((i >> j) & 1) //判断i的第j为是否选择cout << j + 1 << " ";cout << '\n';
}

位运算(二)

void dfs(int u,int state){if(u == n){for(int i=0;i<n;++i)if(state>>i &1)cout<<i+1<<" ";cout<<endl;return ;}dfs(u+1,state);dfs(u+1,state|1<<u);//将state的第u位置为1}

实现组合型枚举

DFS + 剪枝

#include <iostream>
#include <stdio.h>
#include <cstring>using namespace std;int n,m;
int path[100000];void dfs(int stp, int k) {if(k == m){ // 检测 放的元素是否达到m个for (int i = 0; i < k; ++i)printf("%d ", path[i]);putchar('\n');}// 剪枝//选的元素个数已经超过m个了,或者即使再选上剩余的所以数也不够m个if(k >= m || (k+n-stp+1)<m)return ;if (stp > n)return ;for (int i = stp; i <= n; ++i) {path[k++] = i;dfs(i + 1, k);k -- ;}
}int  main() {scanf("%d%d", &n,&m);dfs(1, 0);return 0;
}作者:多元函数
链接:https://www.acwing.com/activity/content/code/content/1963737/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

实现排列型枚举

DFS

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;int n;
bool vis[10];
int path[10];void dfs(int sp){if(sp == n+1){for(int i=1;i<=n;++i)printf("%d ",path[i]);putchar('\n');return ;}for(int i=1;i<=n;++i){if(!vis[i]){ // 用一个bool 数组记录一条路径已经使用过的值,避免重复vis[i] = 1;path[sp] = i; //因为在这里sp就是sp对应的位置应该插入一个数dfs(sp+1);vis[i] = 0; // 回溯}}
}int main(){scanf("%d",&n);memset(vis,0,sizeof(vis));dfs(1);return 0;
}

费解的开关

题目链接

难点:

枚举第一行的所有状态后如何改变原来的,思路是对于位数为1的就改变,并计数。而因为改变会改变原来的状态,所以需要用一个数组来保存下原来的状态在改变之后在恢复回来。在定完第一行后就可以递推下面的行,行是从0~4的,如果为0就改变,之后就检验最后一行是否都是1。

技巧:

对于原来是0的字符变为1,是1的变为0.可以用异或1的方法。

g[xx][yy]  ^= 1;

代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
const int INF = 987654321;
using namespace std;char g[20][20];
int ans;
int dx[5] = {0,1,-1,0,0},dy[5] ={0,0,0,1,-1};void turn(int x,int y){for(int i = 0;i<5;++i){int xx = x+dx[i],yy = y+dy[i];if(xx>=0&&xx<5&&yy>=0&&yy<5){g[xx][yy]  ^= 1;}}
}int work(){for(int k=0;k<(1<<5);++k){int res = 0;char barcup[20][20];memcpy(barcup,g,sizeof g);for(int i=0;i<5;++i)if(k>>i &1){ // 位置为1表明该位置的灯变化res++; //这所以每一步都要计数turn(0,i);}for(int i =0;i<4;++i)for(int j=0;j<5;++j){if(g[i][j] == '0'){res++;turn(i+1,j);}}bool istrue = true;for(int i=0;i<5;++i)if(g[4][i] == '0'){istrue = 0;break;}if(istrue) ans = min(ans,res);memcpy(g,barcup,sizeof g);}if(ans>6)return -1;return ans;
}int  main(){int t;scanf("%d",&t);while(t--){for(int  i=0;i<5;++i)cin>>g[i];ans = INF;ans =  work();printf("%d\n",ans);}return 0;
}

奇怪的汉诺塔

原题链接

代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;const int INF = 98765431;
int n;
int d[100],f[200];int main(){n = 12;d[1] = 1;for(int i=2;i<=n;++i) // 递归算出三个盘子d[i] = 2*d[i-1] + 1;memset(f,0x3f,sizeof f);f[0]  = 0;for(int i=1;i<=n;++i)for(int j=0;j<i;++j)// f[j] 是有四个塔的时候,把前j个搭移到一个搭上。// 之后还要移动回来所以是*2// 之后把剩余的i-j个移动的时候只有3个所以是 d[i-j]f[i] = min(f[i],2*f[j]+d[i-j]);for(int i =1;i<=n;++i)printf("%d\n",f[i]);return 0;
}

分形之城

题目链接

递归+分治+数学坐标系公式+找规律
递归+分治好理解,因为这个题目中最显著的特点就是,不断地重复旋转复制,也就是NN级城市,可以由44个N−1N−1级城市构造,因此我们每次可以不断地分形N−1N−1级,将问题范围不断地缩小即可
这道题目的数学坐标公式,其实一共有两个,一个是高中的数学函数,旋转,这是一个难点,其实可以通过找规律,求解,第二公式则是欧几里得距离公式。(x1−x2)2−(y1−y2)2−−−−−−−−−−−−−−−−−−√(x1−x2)2−(y1−y2)2
最难的就是如何旋转这个正方形 找规律。
总的来说这道题目数学知识较多,考察画图能力,解法自然,数据毒瘤,相信可以给你的NOIP一个有利的一脚。

  • 左上角:我们可以发现,左上角的N−1N−1级矩阵其实就是等级为N−1N−1,也就是上一个矩阵,顺时针旋转90°90°,那么既然如此的话,我们就可以综合yxc老师上课所讲的公式(补充:也就是旋转矩阵,属于大学的线性代数内容),得出转移后的矩阵中的一点坐标从(x,y)(x,y)变为(y,x)(y,x)
  • 左下角:同左上角,它则是逆时针旋转90°90°而且还要水平翻转,也即是沿着XX轴对称,原本逆时针后为(y,−x)(y,−x),然后要对称,xx坐标不变,yy坐标取反,所以坐标为(−y,−x)(−y,−x) 也就是所谓的(2×len−1−y,len−1−x)(2×len−1−y,len−1−x) 最难理解的坐标,具体可以画图理解
  • 右上角和右下角:通过N=2N=2级图发现,其实和N=1N=1是一样的,并没有旋转,只是平移,则右上角坐标为(x,y+len)(x,y+len),右下角坐标为(x+len,y+len)(x+len,y+len)

总的来说以上四种转移,都可以通过画图理解
还有本题数据毒瘤,四舍五入最好是double类型,而且整数类型一定要是long long,否则容易WA!

题解出处:https://www.acwing.com/solution/content/814/

小技巧:
坐标(x,y) 顺时针旋转一定度数后得到的坐标公式是:
(x,y)∣cos⁡θsin⁡θ−sin⁡θcos⁡θ∣(x,y) \left| \begin{matrix} \cos\theta & \sin\theta \\ -\sin\theta & \cos\theta \\ \end{matrix} \right| (x,y)∣∣∣∣​cosθ−sinθ​sinθcosθ​∣∣∣∣​

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define ll long long
#define PLL pair<ll,ll>
PLL calc(ll n,ll m)
{if (n==0)return make_pair(0,0);ll len=1LL<<(n-1),cnt=1LL<<(2*n-2);PLL pos=calc(n-1,m%cnt);ll x=pos.first,y=pos.second;ll z=m/cnt;if (z==0)return make_pair(y,x);if (z==1)return make_pair(x,y+len);if (z==2)return make_pair(x+len,y+len);return make_pair(2*len-1-y,len-1-x);
}
int main()
{//ios::sync_with_stdio(false);int t;scanf("%d",&t);while(t--){ll n,a,b;scanf("%lld%lld%lld",&n,&a,&b);PLL x=calc(n,a-1);PLL y=calc(n,b-1);ll dx=x.first-y.first,dy=x.second-y.second;double ans=(sqrt(double(dx*dx+dy*dy))*10);printf("%0.lf\n",ans);}return 0;
}

基本算法之递推与递归的简单应用相关推荐

  1. 0x02.基本算法 — 递推与递归

    目录 一.递推与递归 二.分治 三.模拟计算机实现递归 四.相应习题: 0.AcWing 92. 递归实现指数型枚举(递归/循环+位运算) 1.AcWing 93. 递归实现组合型枚举 2.AcWin ...

  2. 算法设计与分析 1 递推与递归

    递推与递归 Fibonacci #include<stdio.h> #pragma warning (disabled:4996) #define MAX 100 int f[MAX];/ ...

  3. 算法总结之递推与递归

    递推算法 递归算法大致包括两方面的内容:1)递归起点 : 2)递归关系 递推起点 递归起点一般由题目或者实际情况确定,不由递归关系推出.如果无法确定递归起点,那么递归算法就无法实现.可见,递归起点是递 ...

  4. 算法设计分析之------ 递推与递归篇二

    递推与递归篇二 递归 Secret Cow Code S 黑白棋子的移动 递推(动态规划) 覆盖墙壁 递归 Secret Cow Code S 题目链接:Secret Cow Code S 解题思路 ...

  5. 递推与递归 (区别)

    递推与递归 本文中部分内容转自他人博客,作者相关信息以及博客地址在文末. 概念 递归:从已知问题的结果出发,用迭代表达式逐步推算出问题的开始的条件,即顺推法的逆过程,称为递归. 递归的定义:在一个函数 ...

  6. 递推和递归(C语言)

    文章目录 前言 一.递推原理 1.递推概念 2.递推关系 3.递推特点 4.递推详例 5.解决递推问题的步骤 二.递归原理 1.递归的概念 2.构成递归的条件 3.递归的模板 4.递归详例 三.递推和 ...

  7. 昆虫繁殖(继续理解递推和递归)

    昆虫繁殖(继续理解递推和递归) /*[题目描述] 科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强.每对成虫过x个月产y对卵,每对卵要过两个月长成成虫.假设每个成虫不死,第一个月只有一对 ...

  8. Python 递推 与 递归

    Python 递推 与 递归 结论 递推" :解决问题,需要推算各个数据直接的关系,并以此罗列关系. "递归" : 不是用来解决问题,而是大事化小,小到一定地步,问题迎刃 ...

  9. 斐波那契数列的递推与递归求法

    斐波那契数列的递推与递归求法: OVERVIEW 斐波那契数列的递推与递归求法: (1)递推求Fibonacci: (2)递归求Fibonacci: (3)递归求Fibonacci(记忆化数组优化): ...

最新文章

  1. linux 浏览器源码下载,Android开发:图片浏览器源码
  2. uniapp设置模板路径页面样式混乱解决办法
  3. lncRNA是什么?
  4. 【机器视觉】 dev_get_window算子
  5. pycharm pyqt5 pyrrc_编程基础 | Pycharm安装、配置、快捷键
  6. webstorm 运行android,Windows React Native环境搭建:webstorm+android studio 及解决热更新
  7. SpringBoot(十一)-- 动态数据源
  8. 云应用性能管理哪家强?性能魔方mmTrix自动测评、检测与加速
  9. 机器学习的行业与场景总结
  10. 转行 AI 成为技术大牛,你需要理解这两项技术!
  11. Java存储任意对象_浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象...
  12. access 循环_双11多个品牌创销量新高,ACCESS品牌管理集团背后的全球供应链解码...
  13. 计算机 会议录用率 统计
  14. 56: Recv failure: Connection was reset和55错误解决办法
  15. 中软酒店管理系统CSHIS操作手册_数据结构_数据字典
  16. MATLAB提示错误使用network,优化双隐藏神经网络出现错误使用 network/subsasgnne...
  17. java计算机毕业设计vue教学管理系统MyBatis+系统+LW文档+源码+调试部署
  18. bitnami redmine 4 windows一键式版本安装企业微信插件方法
  19. [linux无线子系统]主动扫描之发送Probe Request帧
  20. 算法——暴力之美(volence‘s beautify of algorithm)

热门文章

  1. linux type命令(用来显示指定命令的类型,判断给出的指令是内部指令还是外部指令,如果给出的指令为外部指令,则显示其绝对路径)
  2. Nginx报错:nginx: [emerg] open() “/usr/local/nginx/../conf/nginx.conf“ failed (2: No such file or direc
  3. python numpy:array、asarray、asanyarray的区别
  4. mybatis中getMapper是怎么通过动态代理得到dao接口的实现类并执行mapper文件sql语句的
  5. java 百度账号注册界面_基于百度AI开放平台的人脸识别的注册登录(1)
  6. Commit failed with error: pathspec 'src/main/java/com/leo/demo/juctest/test.java' did not match any
  7. get方式请求接受参数的方法
  8. 动态添加 ajax,ajax动态的添加内容【原创】
  9. 东师计算机应用基础18秋在线作业3答案,奥鹏东师计算机应用基础15秋在线作业3试卷及答案(4)...
  10. 事件触发控制_前端性能优化:事件的节流throttle与防抖debounce