NOIP 普及组初赛 · NOIP 2012 普及组初赛试题 第 28 题

完善程序 · 答案 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;	
}
答案:falseused[data[i]]=falsejnbreak

考点

输入输出位运算 讲解 →位运算 真题汇总 →分支结构循环结构字符串(string)STL容器基础 讲解 →STL容器基础 真题汇总 →

解题思维

看到全排列回溯 → 先想 used 标记还原与循环边界。

常见错误

used 是‘已占用’非‘已输出’;第④空上界是 n 而非 m;找到可用数后必须 break 而非 continue。

详细解析(节选)

考点:全排列 DFS 回溯|used 数组语义|循环边界控制

程序在做什么

输入 n,m 后,用 DFS 按字典序生成 1~n 中选 m 个数的所有排列。每层从 data[i]+1 到 n 找第一个未用数,填入选中并标记 used,填完 m 个数输出后回溯。

同考点真题

在 OI伴学 里做这道题
登录后可计时作答、查看完整六段式解析,并按你的错题自动生成同类练习。
去刷题先做一次 AI 学情诊断