ZJYYOJ 优美的排列(dfs)[C,C++]

题目及翻译

题面

假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:
I. 第 i 位的数字能被 i 整除
II. i 能被第 i 位上的数字整除
现在输入一个整数 N,请问可以构造多少个优美的排列?

输入

输入样例由多组测试数据组成。每组测试数据第一行输入一个正整数 N ( 1 <= N <= 15 )

输出

输出可以构造的优美的排列的数量

输入样例

2

输出样例

2

提示

参照输入样例:
第 1 个优美的排列是 [1, 2]:
第 1 个位置(i=1)上的数字是1,1能被 i(i=1)整除
第 2 个位置(i=2)上的数字是2,2能被 i(i=2)整除
第 2 个优美的排列是 [2, 1]:
第 1 个位置(i=1)上的数字是2,2能被 i(i=1)整除
第 2 个位置(i=2)上的数字是1,i(i=2)能被 1 整除

题目思路

给学弟学妹写篇题解,小不点们加油!!
有不懂的地方欢迎留言或者微信找我询问~
这题递归的确很方便,比之之前的题目好歹要带回溯了,其实是我没想到不回溯的递归方式
乍一看很麻烦,但是只要透析题目的本质,这题就很简单
对于每一个位置 i,从1到n里选择一个被i整除的数或者i的倍数,标记其被使用过,然后递归下一个位置到结束即可

注意事项

为了与答案匹配,应该选择从1开始的位置递归到n,到达n + 1时才退出

AC代码

C/C++(代码几乎没有变更)

用时72MS 内存1120K 长度347B

#include<stdio.h>
int n;
int vis[20];
int dfs(int cur){//cur用来表示当前所处位置,从1开始到n
	if(cur == n + 1)return 1;//到n+1时说明所有位置都被安排好了,就退出
	int sum = 0;//统计结果,如果结果为0意味着目前情况没有答案
	for(int i=1;i<=n;++i){//从1到n遍历
		if(vis[i])continue;//如果这个数被用过,就跳过
		if((i % cur) && (cur % i))continue;//如果这个数和i互相都不是对方的倍数,就跳过
		vis[i] = 1;//使用这个数
		sum += dfs(cur + 1);//统计使用了i这个数的所有情况
		vis[i] = 0;//回溯
	}
	return sum;
}
int main(){
	while(~scanf("%d",&n)){//循环输入到文件尾
		printf("%d\n",dfs(1));//弹出
	}
	return 0;
}

本文作者 CSDN@扶她小藜
个人主页链接 https://blog.csdn.net/weixin_44579869

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值