洛谷 1088.火星人

这道题就是一个全排列问题,可以用dfs中的全排列型递归做。

思路:首先我们知道,我们需要列举出n个数的全排列方案,并且我们从题目中可以知道,火星人的数字是根据全排列的字典序的顺序进行定义数字的,我们只需要知道在火星人列举出的数组属于字典序中的第几个,然后再加上m,得出当前字典序加上m的方案就行了。

所以我们选择用全排列的递归模板解题,这里可以不要用二维数组存储,因为n<=10000,这样会导致数组越界,所以我们需要想办法优化一下,这时我们想到用dfs中进行输出就行了。所以不用定义二维数组,这跟上一个题是不一样的。

写出来之后,我们需要注意的有两点:

1.当我们判断终止条件的时候需要进行剪枝,因为这里的n很大,当我们已经找到那个唯一的方案数之后终止dfs的搜索就行了,所以我们需要一个标志变量flag,当我们找到这个方案的时候就直接将它变为true,然后就会终止查找;

2.当我们没有生成方案的时候,我们的数组初始是怎样的我们并不知道,因为在我们通常的思路里,没有生成方案之前就全是0,但是,这里的题目有一个要求,就是我们需要按火星人给的这一组数字进行搜索判断,然后再生成方案,这一点需要额外注意!

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath> 
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 10010
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef long long LL;
int n, m, counts;
LL arr[MAX];
LL st[MAX];
LL nono[MAX];
LL heihei;
bool flag = false;
void dfs(LL u) {
    if (flag)
        return;//剪枝
    if (u > n) {
        heihei++;
        if (heihei == m + 1) {
            flag = true;
            for (int i = 1; i <= n; i++) {
                cout << arr[i] << " ";
            }
        }
        return;
    }
    for (LL i = 1; i <= n; i++) {
        if (!heihei) {
            i = nono[u];
        }
        if (!st[i]) {
            st[i] = 1;
            arr[u] = i;
            dfs(u + 1);
            st[i] = 0;
            arr[u] = 0;
        }
    }
}
int main() {
    
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n >> m;
    for (LL i = 1; i <= n; i++)
        cin >> nono[i];
    dfs(1);
    
    return 0;
}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值