题目链接:火星人
思路:这一题一看就是一个全排列问题!
先求出给定序列的全排列是第几个,然后加上 m 后输出这个全排列即可!
看似一道很简单的题!如果采用枚举的话,不用想了,肯定超时啊!!!
我们看一下数据,发现 m 挺小的,那我们就想到了,是不是可以通过枚举 m 来求解呢?
答案当然是肯定的了!
我们先一步到给定的全排列,然后枚举出第 m 个即可!!!。
所以,困难又来了,如何一步到给定的全排列?
我也不会。。。。看了看网上的大佬写的,一起学习下吧!
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn=10000+10;
int n,m,a[maxn],flag,flagx;
bool s[maxn];
void dfs(int step)
{
if(flagx==1)
return;
if(step>n)
{
flag++;
if(flag==m+1)//现在到了我们要加上的那个数的全排列的时候,我们就直接地输出,然后标记flagx,一直return,结束程序
{
for(int j=1;j<=n;j++)
printf("%d ",a[j]);
printf("\n");
flagx=1;
}
return;
}
for(int i=1;i<=n;i++)
{
if(flag==0)
i=a[step];//当还在外星人给出的排列这个阶段的时候,我们就直指外星人给出的序列中的数
if(s[i]==0)
{
s[i]=1;
a[step]=i;
dfs(step+1);
s[i]=0;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs(1);
return 0;
}
可能大家不是很懂dfs中的那个for 其实想一想,我们在求全排列的时候 是递归求的,我们每求得一中全排列,它背后是有一个递归层的
所以当我们想从任意一种排列开始求它后面的排列时,就需要先把
它的这个递归层先建立起来,然后顺着继续递归就好了
结束了吗?!
显然没有。
了解 algorithm 的筒子应该知道,里面就封装好了求全排列的函数!!!
hhhh.....
当然了,有求下一次全排列的肯定就有求上一次全排列的了。。。
#include <bits/stdc++.h>
using namespace std;
int main(){
int a[10000],n,m,i;
cin>>n>>m;//因为cin可以检测换行,所以可以一起读
for (i=1;i<=n;i++) cin>>a[i];//首先要把a数组读入
for (i=1;i<=m;i++) next_permutation(a+1,a+n+1);//循环m次,每次求下一种排列,如果数组是从0读入到n-1的,直接next_permutation(a,a+n)就行了
for (i=1;i<n;i++) cout<<a[i]<<" ";//由于题目说明输出最后没有空格,所以先循环到n-1,输出a[i]加一个空格
cout<<a[n];最后再输出a[n]
}
其实吧。感觉康拓展开应该也差不多可以!!
移步 康拓展开