完善程序 · 答案 falseused[data[i]]=falsejnbreak · 考点:输入输出、位运算、分支结构、循环结构、字符串(string)、STL容器基础
← 整套速查表 NOIP 普及组初赛 全部真题完善程序 (排列数) 输入两个正整数 $n,m(1<n<20,1<m<n)$,在 $1\sim n$ 中任取 $m$ 个数,按字典序从小到大输出所有这样的排列。 例如: 输入:3 2 输出:1 2 1 3 2 1 2 3 3 1 3 2
#include <iostream>
#include <cstring>
using namespace std;
const int SIZE =25;
bool used[SIZE];
int data[SIZE];
int n,m,i,j,k;
bool flag;
int main()
{
cin>>n>>m;
memset(used,false,sizeof(used));
for(i=1;i<=m;i++)
{
data[i]=i;
used[i]=true;
}
flag=true;
while(flag)
{
for(i=1;i<=m-1;i++) cout<<data[i]<<" ";
cout<<data[m]<<endl;
flag= [ ① ] ;
for(i=m;i>=1;i--)
{
[ ② ];
for(j=data[i]+1;j<=n;j++)
if(!used[j])
{
used[j]=true;
data[i]=[ ③ ] ;
flag=true;
break;
}
if(flag)
{
for(k=i+1;k<=m;k++)
for(j=1;j<= [ ④ ];j++)
if(!used[j])
{
data[k]=j;
used[j]=true;
break;
}
[ ⑤ ];
}
}
}
return 0;
}看到全排列回溯 → 先想 used 标记还原与循环边界。
used 是‘已占用’非‘已输出’;第④空上界是 n 而非 m;找到可用数后必须 break 而非 continue。
考点:全排列 DFS 回溯|used 数组语义|循环边界控制
输入 n,m 后,用 DFS 按字典序生成 1~n 中选 m 个数的所有排列。每层从 data[i]+1 到 n 找第一个未用数,填入选中并标记 used,填完 m 个数输出后回溯。