蓝书(算法竞赛进阶指南)刷题记录——CH0302 用非递归实现组合形枚举

版权声明:转载请注明原出处啦(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/81987474

题目:0302递归/非递归实现组合型枚举.

题目大意:输出1~n中选m个数的所有升序排列.

我们用非递归来实现,就得先了解递归在计算机内部的工作原理.

首先,递归运用了一个栈,这个栈是一个用于存储状态的栈.

然后每次运行一个状态的时候,先将所有扩展出来的状态逆向压入栈中,然后继续运行栈顶.

之后若这已经不是第一次碰到这个点了,则重新删除栈顶后当前栈顶应该将剩余部分在运行掉.

那么我们现在要实现这个,我们先将递归形式的代码写出来:

void dfs(int k,int now){
  if (k>m) {
    write();
    return;
  }
  for (int i=now+1;i<=n;i++){
    a[k]=i;
    dfs(k+1,i);
  }
}

解决这道题,我们使用一个栈,其中栈中的每个元素都存储k和now,由于这里不需要回溯,所以运行到了这个点直接就可以把这个点弹出了,具体操作看代码吧.

代码如下:

include<bits/stdc++.h>
  using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=25;
struct Now{
  int k,now;
};
int a[N+9],n,m;
stack<Now> st;
Abigail write(){
  for (int i=1;i<m;i++)
    printf("%d ",a[i]);
  printf("%d\n",a[m]);
}
Abigail dfs(){
  st.push((Now){0,0});      //压入一个初始状态
  while (!st.empty()){
    Now t=st.top();      //取栈顶 
    st.pop();      //直接删除 
    a[t.k]=t.now;
    if (t.k==m) write();
    else for (int i=n;i>t.now;i--)
      st.push((Now){t.k+1,i});      //将状态压入栈 
  }
}
Abigail into(){
  scanf("%d%d",&n,&m);
}
Abigail work(){
}
Abigail outo(){
  if (m==0) return;
  dfs();
}
int main(){
  int T=1;
  while (T--){
    into();
    work();
    outo();
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/81987474