注:本题掌握后可继续做https://www.luogu.com.cn/problem/P1618
一.题目概括
将 1,2,…,9 共 9 个数分成 3 组,分别组成 3 个三位数,且使这 3 个三位数构成 1:2:3 的比例,试求出所有满足条件的 3 个三位数
二.关键点
1.手写全排列:深搜全排列问题
这道题的总体思路就是求出1-9的全排列并将其存在字符串中,分割字符串,求出值(由于不需要输出9的全排列,所以会快很多)
全排列问题是一道很经典的问题,符合深搜的逻辑,精髓是用深搜递归n重循环(深搜复杂度O(n!),本题只有九重,所以复杂度为9!=362880,不超时),判断不重复,标记后,求出具体的排列
以下是全排列的一个示例dfs代码(已通过洛谷P1706)(字符全排列类似):
void dfs(int step,vector<int> lp){
if(step==n){
for(int i=0;i<lp.size();i++)printf("%5d",lp[i]);
printf("\n");
return;
}
else{
for(int i=1;i<=n;i++){
if(!vis[i]){
vis[i]=true;
lp.push_back(i);
dfs(step+1,lp);
lp.pop_back();
vis[i]=false;
}
}
}
}
//vis:记录数组 lp:路径
2.algorithm库自带全排列函数
这种方法适合没有时间,或仅仅输出要用全排列的OIer
示例代码如下(已通过洛谷P1706)
函数中的参数和sort函数类似
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int n;
vector<int> vec;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)vec.push_back(i+1);
do{
for(int i=0;i<vec.size();i++)printf("%5d",vec[i]);
printf("\n");
}while(next_permutation(vec.begin(),vec.end()));
}
三.AC代码
1.解法1:手写全排列
#include <iostream>
#include <cstring>
#define N 9
using namespace std;
bool vis['9'+10];
int _atoi(string s){//字符串->int
int n;
for(int i=0;i<s.size();i++){
n=n*10+(s[i]-'0'); //构造int
}
return n;
}
void dfs(int step,string s){//step:步数(添加了几个数字),s:路径字符串
if(step==N){
int a=_atoi(s.substr(0,3));
int b=_atoi(s.substr(3,3));
int c=_atoi(s.substr(6,3));
if(2*a==b&&a*3==c)cout<<a<<' '<<b<<' '<<c<<endl;
return;
}
else{
for(char i='1';i<='9';i++){
if(!vis[i]){
vis[i]=true;//标记
dfs(step+1,s+i);
vis[i]=false;
}
}
}
}
int main(){
dfs(0,"");
}
时间:
2.解法2:algorithm全排列
#include <iostream>
#include <vector>
#include <algorithm>
#define N 9
using namespace std;
vector<int> vec;
int main(){
for(int i=0;i<N;i++)vec.push_back(i+1);
do{
int a=vec[0]*100+vec[1]*10+vec[2];
int b=vec[3]*100+vec[4]*10+vec[5];
int c=vec[6]*100+vec[7]*10+vec[8];
if(a*2==b&&a*3==c)cout<<a<<' '<<b<<' '<<c<<endl;
}while(next_permutation(vec.begin(),vec.end()));
}
时间: