1.AcWing 92. 递归实现指数型枚举
分析:数据范围n<=15,一看就是指数型的复杂度,这种指数类型的复杂度一般就是dfs+剪枝,每个数字都有两种状态,选或者是不选,开一个数组记录状态,左分支为选了的,右分支为没选的,左右两边递归即可
画出递归搜索树
以n=3为例
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=16;
int st[N];//记录状态
//0表示未考虑,1表示没选,2表示选了
void dfs(int u)
{
if(u>n) //递归结束条件
{
for(int i=1;i<=n;i++)
{
if(st[i]==2)
cout<<i<<" ";
}
cout<<endl;
return;
}
//左分支,没选的
st[u]=1;
dfs(u+1);
st[u]=0;//恢复现场
//右分支,选了的
st[u]=2;
dfs(u+1);
st[u]=0;//恢复现场
}
int main()
{
cin>>n;
dfs(1);
}
2.AcWing 94. 递归实现排列型枚举
分析:输出全排列,n<=9的数据范围,dfs暴力枚举每个位置可以放哪些数,开两个数组,一个数组st记录状态,即当前数字是否被使用过,另一个数组way记录这个当前位置放的数,达到递归出口条件,遍历way数组输出即可,从头开始枚举,输出来的已经是按字典序排好的了
画出递归搜索树:
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=10;
int st[N];
int way[N];
void dfs(int u)
{
if(u>n)
{
for(int i=1;i<=n;i++)
{
cout<<way[i]<<" ";
}
cout<<endl;
return;
}
for(int i=1;i<=n;i++)
{
if(st[i]==0)
{
st[i]=1;
way[u]=i;
dfs(u+1);
st[i]=0;//回复现场
}
}
}
int main()
{
cin>>n;
dfs(1);
}
3.dotcpp1024 母牛的故事
分析:今年的母牛数量=去年的母牛数量+新出生的小母牛数量
新出生的小母牛数量=前三年的母牛数量
所以递推关系式:f(n)=f(n-1)+f(n-3)
首先我想到用递归,但递归是指数级别的复杂度,一般适用于n<=30的数量范围,此题n=55,所以时间超限
dp做法:
根据递推关系式,开一个数组边算边记录下来
/*#include<bits/stdc++.h>
using namespace std;
int fun(int n)
{
if(n<=4)
return n;
else
return fun(n-1)+fun(n-3);
}
int main()
{
int n;
while(cin>>n&&(n!=0))
{
cout<<fun(n)<<endl;
}
}*/
//时间超限
#include<bits/stdc++.h>
using namespace std;
int cow[56]={0,1,2,3,4};
int n;
int main()
{
for(int i=5;i<55;i++)
{
cow[i]=cow[i-1]+cow[i-3];
}
while(cin>>n&&(n!=0))
{
cout<<cow[n]<<endl;
}
}