洛谷P1088

题目链接:火星人


思路:这一题一看就是一个全排列问题!

先求出给定序列的全排列是第几个,然后加上 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]
}

其实吧。感觉康拓展开应该也差不多可以!!

移步 康拓展开

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值