给你一个输出受限的双端队列,限制输出的双端队列即可以从一端插入元素,弹出元素,但是另一端只可以插入不可以删除元素。即每次你可以执行以下三种操作的其中一种:
- 在左边压入一个字符
- 在右边压入一个字符
- 弹出最左边的字符
现在给你 n n n 个字符作为队列的输入,请问最多有多少可能的出队次序,并按字典序打印这些出队次序。
输入格式
第一行一个数 n n n,表示输入的长度
第二行一个长度为 n n n 的字符串
输出格式
第一行一个整数 k k k,表示可能的出队方案数
下面 k k k 行,按字典序输出每种出队方案
样例输入
3
123
样例输出
6
123
132
213
231
312
321
数据规模
对于全部数据保证 1 ≤ n ≤ 7 1≤n≤7 1≤n≤7。
解题思路
虽然题目说是模拟,但是我们不尝试一下别的方法肯定不会甘心的,所以尝试理解序列满足的规则。
以样例输入为例子,我们留出三个位置 □□□ □□□ □□□。
考虑一种简单的情况,我们在所有元素入队之后再进行出队操作,那么一下逻辑成立:
首先对于 a 1 a_1 a1,我们可以任意指定它的位置;
然后对于 a 2 a_2 a2,因为 a 1 a_1 a1的位置已经确定了, a 2 a_2 a2必须在 a 1 a_1 a1的前方或者 a 1 a_1 a1的后方,其位置选择受限;
同理可知 a 3 a_3 a3位置选择同样受限。
似乎并没有可以用来优化代码的规律存在,所以我们还是老老实实回去模拟。
模拟双端队列采用STL提供的deque
容器,由于搜索的结果存在重复,采用set
存储结果去重(同时set
会自动将结果按字典序排序)。
#include <iostream>
#include <deque>
#include <set>
using namespace std;
const int max_n = 7;
string in_str;
int n;
set<string>ans;
采用dfs
搜索可能的出队方案:
void dfs(int step, deque<char>d, string str) {//dfs状态
//终止条件
//dfs主体
//返回后操作
}
接下来我们对dfs
代码功能进行实现。
实现具体的代码之前我们需要知道每一步有几种可能的操作:
1)在首部插入一个元素;
d.push_front(in_str[step]);
dfs(step + 1, d, str);
d.pop_front();
2)在尾部插入一个元素;
d.push_back(in_str[step]);
dfs(step + 1, d, str);
d.pop_back();
3)出队一个元素;
while (!d.empty()) {
str += d.front(); d.pop_front();
//在首部插入一个元素
d.push_front(in_str[step]);
dfs(step + 1, d, str);
d.pop_front();
//在尾部插入一个元素
d.push_back(in_str[step]);
dfs(step + 1, d, str);
d.pop_back();
}
以上步骤实现完后,终止条件显而易见:
if (step == n) {
while (!str.empty()) {
str += d.front(); d.pop_front();
ans.insert(str);
}
return;
}
dfs
完整代码如下:
void dfs(int step, deque<char>d, string str) {//dfs状态
//终止条件
if (step == n) {
while (!str.empty()) {
str += d.front(); d.pop_front();
ans.insert(str);
}
return;
}
//dfs主体
//在首部插入一个元素
d.push_front(in_str[step]);
dfs(step + 1, d, str);
d.pop_front();//返回后操作
//在尾部插入一个元素
d.push_back(in_str[step]);
dfs(step + 1, d, str);
d.pop_back();//返回后操作
//出队一个元素
while (!d.empty()) {
str += d.front(); d.pop_front();
//在首部插入一个元素
d.push_front(in_str[step]);
dfs(step + 1, d, str);
d.pop_front();//返回后操作
//在尾部插入一个元素
d.push_back(in_str[step]);
dfs(step + 1, d, str);
d.pop_back();//返回后操作
}
}
最后,AC代码如下:
#include<iostream>
#include <set>
#include <deque>
using namespace std;
const int max_n = 7;
int n;
string in_str;
set<string>ans;
void dfs(int step, deque<char>d, string str) {//dfs状态
//终止条件
if (step == n) {
while (!d.empty()) {
str += d.front(); d.pop_front();
}
ans.insert(str);
return;
}
//dfs主体
//在首部插入一个元素
d.push_front(in_str[step]);
dfs(step + 1, d, str);
d.pop_front();//返回后操作
//在尾部插入一个元素
d.push_back(in_str[step]);
dfs(step + 1, d, str);
d.pop_back();//返回后操作
//出队一个元素
while (!d.empty()) {
str += d.front(); d.pop_front();
//在首部插入一个元素
d.push_front(in_str[step]);
dfs(step + 1, d, str);
d.pop_front();//返回后操作
//在尾部插入一个元素
d.push_back(in_str[step]);
dfs(step + 1, d, str);
d.pop_back();//返回后操作
}
}
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
deque<char>d;
cin >> n;
cin >> in_str;
dfs(0, d, "");
cout << ans.size() << endl;
for (auto iter : ans) cout << iter << endl;
return 0;
}