トピック
の時間計算量の分析:
ビデオ全体で、計算された数は1億を超えず、通常はタイムアウトしないと述べられています。この質問は、Cが25をベース、13をトップとして計算されます。
出力がまだあるため、結果に13 = 5200300(13はこの質問のm)を掛けます。各組み合わせは最大13回出力する必要があります。 。
最終的な答え* 5200300 13 = 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;
}
yTotalコード
分析図:
#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;
}