51NOD 3055选数字v3

题目:

小明很喜欢选数字,现在小明得到 𝑛 个数,他想得到从 𝑛 个数里面选取 𝑘 个数的所有方案,由于小明的作业很多,现在没有时间解决这个问题,聪明的你可以帮助小明解决这个问题吗?

输入数据

输入包括两行数据,第一行包括两个数 𝑛(1≤𝑛<25) , 𝑘(1≤𝑘≤𝑚𝑖𝑛(𝑛,19)), 表示数列数的个数以及要从数列里面选取数的个数。
第二行 𝑛 个数表示该数列的 𝑛 个数 (0<𝑎𝑖≤100,𝑎𝑖 表示数列里面的数, 𝑎𝑖 可能有重复)。
(两个数之间用空格分开)。

输出数据

按字典序输出所有的方案(格式参照样例)

数据范围

对于 10% 的数据, 1≤𝑛≤5 , 𝑘≤𝑛
对于 50% 的数据, 1≤𝑛≤10 , 𝑘≤𝑛
对于 100% 的数据, 1≤𝑛≤24 ,𝑘≤min(n,19)

样例:

输入:

4 2
1 1 2 3

输出:

1 1
1 2
1 3
2 3

数据范围

从 (1,1,2,3)4 个数字里面选 2 个,有 (1,1),(1,2),(1,3),(2,3) 四种选法。

解题技巧:

为了保证输出的字典序,先对给出的数字进行排序,如果有相同的数字,那么排序后会挨在一起。

此时如果直接套用从 𝑛 个数中选择 𝑚 个数的递归,由于 𝑎𝑖 中有相同的数字,因此会出现完全重复的选择。

为了不出现重复的选择,我们规定如果挨着的两个数字相同,假如前一个没有选,后一个也不能选。

这样需要用一个 𝑏𝑜𝑜𝑙 数组记录选或未选的状态。剩下的逻辑就同 𝑛 个数中选 𝑚 个数一样了。按照之前的方法递归处理即可。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,k,nums[26],sel[26];
bool flag[26];
void DFS(int index,int min){
    if(index==k){
        for(int i=0;i<k;i++)
            cout<<sel[i]<<" ";
        cout<<endl;
        return;
    }
    for(int i=min;i<=n;i++){
        if(nums[i]==nums[i-1]&&!flag[i-1])
            continue;
        sel[index]=nums[i];
        flag[i]=true;
        DFS(index+1,i+1);
        flag[i]=false;
    }
}
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>nums[i];
    sort(nums+1,nums+n+1);
    DFS(0,1);
    return 0;
}

注:原文来自51NOD,为@小罐头甜编辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值