描述
There are N buttons on the console. Each button needs to be pushed exactly once. Each time you may push several buttons simultaneously.
Assume there are 4 buttons. You can first push button 1 and button 3 at one time, then push button 2 and button 4 at one time. It can be represented as a string “13-24”. Other pushing ways may be “1-2-4-3”, “23-14” or “1234”. Note that “23-41” is the same as “23-14”.
Given the number N your task is to find all the pushing ways.
输入
An integer N. (1 <= N <= 8)
输出
Output the different pushing ways in lexicographical order.
For the same pushing way output the smallest string in lexicographical order as representative.
样例输入
3
样例输出
1-2-3
1-23
1-3-2
12-3
123
13-2
2-1-3
2-13
2-3-1
23-1
3-1-2
3-12
3-2-1
###题意
在1-n的全排列中间插入“-”号,输出所有不同的串。
###思路:
本题的数据范围只有N <= 8,又要求输出所有的解。比较容易想到就是穷举/暴搜。
不过我们仍应该先估计一下解的数量的上界。考虑每种表示法都是一个1~N的排列中插入若干个减号,所以解的数量不超过N! * 2^(N-1)。当N=8时大约是5000000,可以接受
具体dfs的方法是首先枚举以每个数开头的情况,所有情况枚举完之后考虑将“-”号用数字覆盖掉。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 128;
bool vis[maxn];
char ans[maxn] = "-";
void dfs(int ptr, int cnt,int n)
{
if (cnt == 0) {
for (int i = 1; i < ptr; ++i)
cout << ans[i];
cout << endl;
return;
}
if (ans[ptr-1] == '-') { //枚举以每个数字开头的情况
for (int i = 1; i <= n; ++i) {
if (vis[i]) continue;
vis[i] = true;
ans[ptr] = i+'0';
dfs(ptr+1,cnt-1,n);
vis[i] = false; //回溯
}
return;
}
ans[ptr] = '-'; //前一个位置已经是数字了,那么当前位置可以放“-”
dfs(ptr+1,cnt,n);
for (int i = ans[ptr-1]-'0'+1; i <= n; ++i) { //用比前一个位置大的数把“-”覆盖
if (vis[i]) continue;
vis[i] = true;
ans[ptr] = i+'0';
dfs(ptr+1,cnt-1,n);
vis[i] = false; // 回溯
}
}
int main()
{
int n;
cin >> n;
dfs(1,n,n);
return 0;
}