0x02
1.递归实现组合型枚举
描述
从 1~n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。n>0, 0<=m<=n, n+(n-m)<=25。
输入格式
两个整数n,m。
输出格式
按照从小到大的顺序输出所有方案,每行1个。
首先,同一行内的数升序排列,相邻两个数用一个空格隔开。其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如1 3 9 12排在1 3 10 11前面)。
样例输入
5 3
样例输出
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
基于上一章的递归实现指数型枚举,我们只需要在原有的基础上进行剪枝即可
剪枝方法如下:
if(v.size()>m||v.size()+(n-x+1)<m){
return;
}
代码如下
#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector<int>ans;
void dfs(int k){
if(ans.size()>m||ans.size()+(n-k+1)<m){
return;
}
if(k==n+1){
for (auto i : ans)
printf("%d ", i);
printf("\n");
return;
}
ans.push_back(k);
dfs(k+1);
ans.pop_back();
dfs(k+1);
}
int main(){
scanf("%d%d",&n,&m);
dfs(1);
return 0;
}
2.递归实现排列型枚举
描述
把 1~n 这 n(n<10) 个整数排成一行后随机打乱顺序,输出所有可能的次序。
输入格式
一个整数n。
输出格式
按照从小到大的顺序输出所有方案,每行1个。 首先,同一行相邻两个数用一个空格隔开。其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面。
样例输入
3
样例输出
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
solve函数中的参数k表示当前已经枚举了多少个数,solve函数里对1-n的数进行遍历,如果该数没有被枚举即(book[i]==0),则将其枚举
代码如下:
#include<iostream>
using namespace std;
int n;
int book[10];
int ans[10];
void solve(int k){
if(k==n+1){
for(int i=1;i<n;i++){
printf("%d ",ans[i]);
}
printf("%d\n",ans[n]);
return;
}
for(int i=1;i<=n;i++){
if(!book[i]){
book[i]=1;
ans[k]=i;
solve(k+1);
book[i]=0;
ans[k]=0;
}
}
}
int main(){
scanf("%d",&n);
solve(1);
return 0;
}
3.费解的开关
本题为一道递推题目,我们可以容易知道,如果前i行不能再被操作了,那第i行只能通过第i+1行的操作才能改动第i行,根据这个公理,我们枚举第1行所能执行的所有操作,即从0枚举到1<<5-1,从而将第1行“固定”下来,然后根据第1行到第4行的灯的状态来修改其对应下一行位置的灯的状态
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
using namespace std;
vector<vector<char>>arr(5, vector<char>(5));
vector<vector<char>>a(5, vector<char>(5));
int ans = -1;
int dir[4][2] = {
{0,1},
{0,-1},
{1,0},
{-1,0}
};
bool isborder(int i, int j) {
return i >= 0 && i < 5 && j >= 0 && j < 5;
}
void change(int x, int y) {
arr[x][y] = arr[x][y] == '0' ? '1' : '0';
for (int i = 0; i < 4; i++) {
int nx = x + dir[i][0]; int ny = y + dir[i][1];
if (isborder(nx, ny)) {
arr[nx][ny] = arr[nx][ny] == '0' ? '1' : '0';
}
}
}
void print() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
printf("%c", arr[i][j]);
}
printf("\n");
}
}
void solve() {
for (int state = 0; state < 1 << 5; state++) {
arr = a;
int tmp = 0;
for (int i = 0; i < 5; i++) {
if (state & 1 << i) {
change(0, i); tmp++;
}
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i != 4 && arr[i][j] == '0') {
tmp++; change(i + 1, j);
}
else if (i == 4 && arr[i][j] == '0') {
tmp = 1 << 10;
}
}
}
if (tmp <= 6) {
if (ans == -1) {
ans = tmp;
}
else {
ans = min(ans, tmp);
}
}
}
return;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
ans = -1;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
cin >> a[i][j];
}
}
solve();
printf("%d\n", ans);
}
return 0;
}