• 递推与递归


    92. 递归实现指数型枚举 - AcWing题库

    1. #include
    2. using namespace std;
    3. const int N=17;
    4. int n;
    5. bool vis[N];//记录某一个数是否出现过
    6. void dfs(int dep){
    7. // if(vis[dep])continue;//没有这一句 因为一定不会有已经选过的数
    8. if(dep==n+1){//对于每个数都做完了选与不选的决定
    9. for(int i=1;i<=n;i++){
    10. if(vis[i])cout<' ';
    11. }
    12. cout<<'\n';
    13. return ;//记得要return
    14. }
    15. vis[dep]=1;
    16. dfs(dep+1);
    17. vis[dep]=0;
    18. dfs(dep+1);
    19. }
    20. int main(){
    21. cin>>n;
    22. dfs(1);
    23. return 0;
    24. }

    93. 递归实现组合型枚举 - AcWing题库

    1. #include
    2. using namespace std;
    3. const int N=100;
    4. int a[N];
    5. int n,m;//n个数中选择m个
    6. int vis[N];
    7. void dfs(int dep,int st){//st数组是为了保证顺序每次只往后面找
    8. if(dep==m+1){//选够m个数了 该选第m+1个数了
    9. for(int i=1;i<=n;i++){
    10. if(vis[i]==1)cout<" ";
    11. }
    12. cout<<'\n';
    13. return ;
    14. }
    15. for(int i=st;i<=n;i++){
    16. if(!vis[i]){
    17. vis[i]=1;//这层有一个数 才去搜索下一层(重要)
    18. dfs(dep+1,i+1);//这里是i+1 因为第i个数字做出判断之后下次要判断的应该是它后面的数
    19. vis[i]=0;
    20. }
    21. }
    22. }
    23. int main(){
    24. cin>>n>>m;
    25. for(int i=1;i<=n;i++)a[i]=i;
    26. dfs(1,1);
    27. return 0;
    28. }

     94. 递归实现排列型枚举 - AcWing题库

    1. #include
    2. using namespace std;
    3. const int N=17;
    4. int n;
    5. bool vis[N]={};//记录某一个数是否出现过
    6. vector<int>ans;
    7. void dfs(int dep){//这里的dep表示的是够多少个数
    8. if(dep==n+1){
    9. for(auto i:ans)cout<' ';
    10. cout <<'\n';
    11. return ;
    12. }
    13. for(int i=1;i<=n;i++){
    14. if(vis[i])continue;
    15. vis[i]=1;
    16. ans.push_back(i);
    17. dfs(dep+1);//这里要是搜索下一个位置 一定要是dep+1
    18. vis[i]=0;
    19. ans.pop_back();
    20. }
    21. }
    22. int main(){
    23. cin>>n;
    24. dfs(1);
    25. return 0;
    26. }
    1. #include
    2. using namespace std;
    3. const int N=17;
    4. int n;
    5. bool vis[N]={};//记录某一个数是否出现过
    6. vector<int>ans;
    7. void dfs(int dep,int st){//这里的dep表示的是够多少个数
    8. if(dep==n+1){
    9. for(auto i:ans)cout<' ';
    10. cout <<'\n';
    11. return ;
    12. }
    13. for(int i=st;i<=n;i++){
    14. if(vis[i])continue;
    15. vis[i]=1;
    16. ans.push_back(i);
    17. dfs(dep+1,st+1);//这里要是搜索下一个位置 一定要是dep+1
    18. vis[i]=0;
    19. ans.pop_back();
    20. }
    21. }//这样的意思是从第一个数开始搜 答案一定要够n个数才能输出
    22. int main(){
    23. cin>>n;
    24. dfs(1,1);
    25. return 0;
    26. }

    1537. 递归实现排列类型枚举 II - AcWing题库

    1. #include
    2. using namespace std;
    3. const int N=12;
    4. int a[N],vis[N];
    5. int n;
    6. vector<int>ans;
    7. void dfs(int dep){
    8. if(dep==n+1){
    9. for(int i=0;i" \n"[i==n-1];
    10. return ;
    11. }
    12. for(int i=1;i<=n;i++){
    13. if(!vis[i]){
    14. vis[i]=1;
    15. ans.push_back(a[i]);
    16. dfs(dep+1);
    17. ans.pop_back();
    18. vis[i]=0;
    19. while(a[i + 1] == a[i]) i++;//剪去重复的 每一个数后面会分出来不同的枝,
    20. //使相同的数分出来的相同枝只出现一次,可以避免重复输出
    21. }
    22. }
    23. return ;
    24. }
    25. int main(){
    26. cin>>n;
    27. for(int i=1;i<=n;i++)cin>>a[i];
    28. sort(a+1,a+n+1);
    29. dfs(1);
    30. return 0;
    31. }

     717. 简单斐波那契 - AcWing题库

    1. #include
    2. using namespace std;
    3. int n,q;
    4. const int N=100007;
    5. int a[N];
    6. int dp[N];
    7. void solve(){
    8. dp[1]=0;
    9. dp[2]=1;
    10. dp[3]=1;
    11. for(int i=4;i<=n;i++)dp[i]=dp[i-1]+dp[i-2];
    12. for(int i=1;i<=n;i++)cout<' ';
    13. }
    14. int main(){
    15. int t=1;
    16. cin>>n;
    17. while(t--)solve();
    18. return 0;
    19. }

    唯一分解定理:一个数可以由若干个质数的若干次方相乘得到

    也可以通过若干个2的次方相加得到

    95. 费解的开关 - AcWing题库

    好难啊这题我哭死了

    1. #include
    2. using namespace std;
    3. const int N = 6;
    4. int dx[N] = {-1, 0, 1, 0, 0}, dy[N] = {0, 1, 0, -1, 0};
    5. char g[N][N], backup[N][N];
    6. // 这个操作是把(x, y)以及上下左右的灯都变成相反的颜色
    7. void turn (int x, int y)
    8. {
    9. for (int i = 0; i < 5; i ++ )
    10. {
    11. int a = x + dx[i], b = y + dy[i];
    12. //如果在边界外边,直接忽略即可
    13. if (a < 0 || a >= 5 || b < 0 || b >= 5) continue;
    14. g[a][b] ^= 1; //异或,不同的时候就变成相反的数
    15. //同0异1
    16. }
    17. }
    18. int main()
    19. {
    20. int n;
    21. scanf("%d", &n);
    22. while(n -- )
    23. {
    24. // 按行输入,把每一行当成一个字符串
    25. for (int i = 0; i < 5; i ++ ) cin >> g[i];
    26. int res = 0x3f3f;
    27. // 这里我们枚举了第一行的32种按法,不用管是亮是灭,把第一行所有情况都按一遍
    28. // 按每种情况的第一行,去遍历接下来的行
    29. // 枚举32种第一行的按法只是可能会减少步数,如果直接从第二行开始答案一定是固定的了,找不到最优解或者可能没有解
    30. //枚举第一行的意义是:不需要在意第一行的灯是灭是暗,只需把第一行的按法枚举一遍,也就是我们说的 “操作”,
    31. //每个位置都有两种选择,按(用1表示)或者不按(用0表示),遍历这32种操作引发的情况,
    32. //每一次再通过res = min(res, step);把最小步数存一下,就能找到最优解
    33. for (int op = 0; op < 32; op ++ ){//枚举第一行每一种状态 //好好想想这里为什么要是<32:11111是31
    34. //是说我们输入的已知的是第一行灯亮或暗的状态,而我们枚举的32种是我们对灯的操作,按还是不按。
    35. // 我在对这种情况操作的时候,得先备用一下
    36. // 把原始数组备份一下,然后操作g,操作完了还原,然后再操作
    37. memcpy(backup, g, sizeof g);
    38. int step = 0;
    39. // 第一行的按法(在这里 1 表示按了, 0 表示不按),这里只是为了输出第一行按完之后的状态
    40. for (int i = 0; i < 5; i ++ )
    41. if (op >> i & 1) // 数字2 对应了 00010 表示第2个位置的按一下
    42. // 00010 >> 1 & 1 是1 所以turn(0, 1) 就是第一行第二个位置
    43. { // 数字3 对应了00011 表示第1 和第2个位置的按一下
    44. step ++ ;
    45. turn (0, i);;
    46. }
    47. // 然后通过第一行按完之后的状态,按234行
    48. for (int i =0; i < 4; i ++ )
    49. for (int j = 0; j < 5;j ++ )
    50. if (g[i][j] == '0')
    51. {
    52. step ++;
    53. turn (i + 1, j); // 如果这个位置是灭的,就按下一行对应的位置
    54. }
    55. bool dark = false;
    56. for (int j = 0; j < 5; j ++ )
    57. if (g[4][j] == '0')
    58. {
    59. dark = true;
    60. break;
    61. }
    62. // 对于32种情况的这一种,如果所有的全亮就记录下步数(事实上只记录了最后一行是否dark)
    63. if (!dark) res = min(res, step);
    64. memcpy (g, backup, sizeof g);
    65. }
    66. if(res > 6) res = -1;
    67. cout << res << endl;
    68. }
    69. return 0;
    70. }

    116. 飞行员兄弟 - AcWing题库 

    1. //一个把手改变,会使所在行列的所有把手全部反转
    2. //特点:①在最优解里面每个把手只按一次,按两次没有区别,
    3. //②按的顺序无关紧要,最终取决于这个把手按的次数!!!
    4. //思考这个题可以递推出来吗? 答案是:很难
    5. //可以想一想,前面的题都是通过某种顺序,每一次都是影响一个灯泡,但是这个题
    6. //不能使用前面的办法,因为操作一次会影响好多灯泡。所以想一想朴素做法
    7. //我们发现这个题的数据范围很小,所以尝试用暴力解决ac
    8. //暴力思路:①16个开关,所有开关的状态数量想一想是多少? 答案是2^16!这个我感觉
    9. //我这么笨还是可以想出来的,往后怎么想呢?
    10. //状态数量即最大操作次数2^16(65536),既然也不大,那就①枚举所有的方案,
    11. //然后按照这个方案来操作
    12. //②如果可以实现把手全开,证明此方案合法
    13. //③然后统计这个方案里面需要操作的把手数量
    14. //④在所有能按的开关数量里取一个最小值
    15. //ac
    16. //输出方案注意:若两种方案步数相同,按字典序(先按横坐标排序,再按纵坐标排序)
    17. #include
    18. //这个宏定义其实也就最后输出的时候应用了(如果我没猜错的话),但是y总的习惯就是好习惯!
    19. #define x first
    20. #define y second
    21. using namespace std;
    22. typedef pair<int,int> PII;
    23. const int N=5;
    24. char g[N][N],backup[N][N];
    25. //映射函数
    26. int get(int x,int y){
    27. return x*4+y;//返回第x行第y列上的数是多少
    28. }
    29. void turn_one(int x,int y){
    30. if(g[x][y]=='+') g[x][y]='-';
    31. else g[x][y]='+';
    32. }
    33. void turn_all(int x,int y){
    34. for(int i=0;i<4;i++)
    35. {
    36. turn_one(x,i);//关闭这一行所有的
    37. turn_one(i,y);//关闭这一列的全部
    38. //xy被关闭了两次 相当于没变
    39. }
    40. turn_one(x,y);//对xy也要改变
    41. }
    42. int main(){
    43. for(int i=0;i<4;i++)
    44. for(int j=0;j<4;j++)
    45. cin>>g[i][j];
    46. vector res;//这是记录方案所需要的结构
    47. //枚举所有的方案
    48. for(int op=0;op<(1<<16);op++){//枚举每一种方案 1代表我们要去操作那个灯
    49. vector temp;//temp里面存的是方案
    50. //先备份一下,为什么?因为这又不是最终方案,我们要把所有方案都试一遍,求最少的
    51. memcpy(backup,g,sizeof g);
    52. //枚举16个位置,进行操作
    53. for(int i=0;i<4;i++)
    54. for(int j=0;j<4;j++)
    55. if(op>>get(i,j)&1) //如果当前位置是1(我们在方案中准备操作)的话--get的作用就是返回二进制数中那一位是第几位,从而判断是否为1
    56. {
    57. temp.push_back({i,j});
    58. //按一下开关
    59. turn_all(i,j);
    60. }
    61. //判断所有灯泡是否全亮
    62. bool has_closed=false;
    63. for(int i=0;i<4;i++)
    64. for(int j=0;j<4;j++)
    65. if(g[i][j]=='+') has_closed=true;
    66. if(has_closed==false)
    67. {
    68. //如果方案为空或者他的操作数大于我们刚存好的新的方案,那么就修改它
    69. if(res.empty()||res.size()>temp.size()) res=temp;
    70. }
    71. //还原回来,供下一个方案操作
    72. memcpy(g,backup,sizeof g);
    73. }
    74. //因为没说无解,所以可以猜想一下一定有解
    75. cout<size()<<'\n';
    76. //这里的迭代函数就是一种简便写法,不要误解
    77. //另外原题下标从1开始,所以下面加1了
    78. for(auto op:res) cout<1<<" "<1<<'\n';
    79. //for(int i=0;i
    80. // cout<
    81. //}
    82. return 0;
    83. }

     1208. 翻硬币 - AcWing题库

    1. #include
    2. using namespace std;
    3. const int N=107;
    4. char change(char &ch){
    5. if(ch=='*') return 'o';
    6. return '*';
    7. }
    8. char a[N];
    9. char b[N];
    10. int main(){
    11. //读不进去可以尝试 cin>>s+1,cin>>s,cin.ignore(),getline(cin,a),cin.getline(a,N);
    12. cin.getline(a,N);
    13. cin.getline(b,N);
    14. // cin>>(a+1);
    15. // cin>>(b+1);
    16. int n = strlen(a);
    17. int step = 0;
    18. for(int i = 0; i < n; i++){
    19. if(a[i] != b[i]){
    20. a[i] = change(a[i]);
    21. if(i+1 < n) {
    22. a[i+1] = change(a[i+1]);
    23. }
    24. step++;
    25. }
    26. }
    27. cout << step;
    28. return 0;
    29. }

     

     

  • 相关阅读:
    hdfs清理数据后,Blocks Pending Deletion持续增长导致磁盘不释放问题记录
    自组织是管理者和成员的双向奔赴
    java基于springboot+vue+elementui的电子产品交流论坛
    代码随想录算法训练营19期第50天
    云原生之使用Docker部署ServerBee服务器监控工具
    html web前端,点击发送验证码,按钮60秒倒计时
    【网络安全 --- xss-labs靶场通关(11-20关)】详细的xss-labs靶场通关思路及技巧讲解,让你对xss漏洞的理解更深刻
    pip install rosbag最正确方法网上其他都不对
    【Apache Hudi】一种基于增量日志文件数的压缩策略
    算法日常训练11.28(813.最大平均值和的分组)
  • 原文地址:https://blog.csdn.net/Shuzi_master7/article/details/136738178