题目
关于时间复杂度的分析
y总的视频中讲到算出的数不超过1亿,一般不会超时。本题是C以25为底 13为上算出结果乘13 = 5200300(13就是本题的m)
因为还有输出,每个组合最多需要输出13次
最后答案*520030013= 67603900 **
自己超时的代码,虽然超时了,但是这是自己认真改写的,下次继续加油!
这是基于(AcWing 94 .递归实现排列型枚举 )题改写的,94题没有(每一行从小到大排序的规则)这题需要加上代码,使输出从小到大。
超时代码
#include<iostream>//注意本题是 字典排序
#include<cstdio>//时间是 n!
#include<cstring>
#include<algorithm>
using namespace std;
const int N=10;
int n,m;
int state[N];// 0 表示还没放数,1~n表示放了哪个数
bool used[N]; // true表示用过,false表示还未用过
void dfs(int u)
{
if(u>m) // 因为输出为m个,所以当u=m+1时就可以进行输出
{
for(int i=1;i<m;i++)//!!!与94题不一样的地方,这里会去掉不是顺序的输出
{
if(state[i+1]<state[i])
{
return;
}
}
for(int i=1;i<=m;i++){
// 打印方案
printf("%d ", state[i]);
}
puts("");
return ;
}
// 依次枚举每个分支,即当前位置可以填哪些数
for(int i=1;i<=n;i++){
if(!used[i]){
state[u]=i;
used[i]=true;
dfs(u+1);
//恢复现场
state[u]=0;
used[i]=false;
}
}
}
int main()
{
scanf("%d %d",&n,&m);
dfs(1);
return 0;
}
y总代码
分析图:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 30;
int n, m;
int state[N];//存储每次输出的数组
void dfs(int u, int start)
{
if (u-1 + n - start +1< m) return; // 剪枝 (150->50ms)速度加快三倍
//每个数组最多可以输出(u-1 + n - start +1)个 ,如果它<m,这组数据已经不用再进行考虑了 (对应的是树中的!红错号)
if(u>m)
{
for (int i = 1; i <= m; i ++ ) printf("%d ", state[i]);
puts("");
return;
}
for (int i = start; i <= n; i ++ )//因为需要顺序输出,所以每次从start开始(对应第28行)
{
state[u] = i;
dfs(u + 1, i + 1);//与其他(递归)不同的是多了 i+1,因为这道题需要顺序输出,start每次都需要+1
state[u] = 0; // 恢复现场
}
}
int main()
{
scanf("%d%d", &n, &m);
dfs(1, 1);
return 0;
}