问题:JM同学在研究排列排列时发现一种有趣的组合,命名成友好组合。
当两个数的二进制表示中至少有KK个位置上的值不同,则称这两个数是相对安全。
例如:
数字60转成二进制为:0 1 1 1 1 0 0
数字85转成二进制为:1 0 1 0 1 0 1
加粗位置上对应的值不同,60与85共有4个位置上的不同
他对友好组合的定义为:在NN个数中(0,1,2,…N-1)(0,1,2,…N−1)选出MM个数,这MM个数中任意两个都是相对安全的。
你能够帮wlxsq找出一种友好组合吗?当然,如果有多组满足条件的解,请输出字典序最小的解。
输入
输入一行包含三个整数:N,M,KN,M,K,其表示的意思如题目描述
输出
输出字典序最小的友好组合,共MM个十进制数。从小到大排序,相邻两个数字中间用空格隔开,每1010个一行。
数据保证至少能找到一种满足条件的友好组合
样例
输入
8 2 2
输出
0 3
输入
256 5 4
输出
0 15 51 60 85
提示
数据规模
1≤N≤256,1≤M≤64,1≤K≤7,数据保证NN均为22的幂次
解题思路
这一题是竞码编程蓝桥杯模拟赛的题,据说达到了b+的难度,额,我最后爆零,编译错误(淦!理由是蓝桥杯里应该不能用itoa)
这一题的思路是,深度优先dfs,创建一个结果序列,先将0加入到序列,从1开始往大找,每次找一个数时,将它与结果序列中的每一个数进行检测,符合条件就加入序列。直到找齐n个数。
具体的代码如下 ,dfs模板 加了一个check做判断,判断用的是 按位与比较。
源码(C++)
#include<bits/stdc++.h>
using namespace std;
int book[257]={0};
int res[64];
int m,n,k;
bool check(int step,int i)
{
for(int j=0;j<step-1;j++)//将i和res的前step-1个数进行检测
{
int a=res[j];
int b=i;
int sum=0;
for(int x=0;x<8;x++)
{
if((a&1)!=(b&1))
{
sum++;
}
a=a>>1;
b=b>>1;
}
if(sum<k)
{
return 0;
}
}
return 1;
};
void dfs(int step)
{
if(step==n+1)//找完了
{
for(int i=0;i<n;i++)
{
cout<<res[i];
if(i<n-1)
cout<<" ";
}
exit(0);
}
for(int i=0;i<m;i++)
{
if(book[i]==0&&check(step,i))
{
res[step-1]=i;
book[i]=1;
dfs(step+1);
book[i]=0;
}
}
};
int main()
{
cin>>m>>n>>k;
dfs(1);
}