DP-Algo
This commit is contained in:
100
Algorithm/DP-DynamicProgramming/Classification.md
Normal file
100
Algorithm/DP-DynamicProgramming/Classification.md
Normal file
@@ -0,0 +1,100 @@
|
||||
### 动态规划的分类
|
||||
|
||||
动态规划(Dynamic Programming, DP)是一种算法设计范式,用于解决具有重叠子问题和最优子结构的问题。它通过将问题分解成更小的子问题,并存储子问题的解来避免重复计算,从而提高效率。DP 的核心是状态定义、状态转移方程和边界条件。
|
||||
|
||||
DP 可以根据问题的结构和状态表示方式进行分类。常见的分类包括线性 DP、区间 DP、树形 DP、状态压缩 DP、数位 DP、背包 DP(有时视为线性 DP 的子类)、概率 DP 和博弈 DP 等。下面我将详细介绍每个分类,包括定义、特点、适用场景,并给出典型例子。对于每个例子,我会简要描述问题、状态定义和转移方程。如果需要代码实现,我可以进一步提供(这里用 Python 示例)。
|
||||
|
||||
#### 1. **线性 DP**
|
||||
- **定义与特点**:问题可以沿着一个线性序列(如数组、字符串)进行处理,通常从左到右或从小到大递推。状态通常是一维或二维数组,转移简单,时间复杂度一般为 O(n) 或 O(n^2)。
|
||||
- **适用场景**:序列优化问题,如最长子序列、路径计数等。
|
||||
- **例子**:
|
||||
- **斐波那契数列**:计算第 n 项斐波那契数(F(n) = F(n-1) + F(n-2))。
|
||||
- 状态:dp[i] 表示第 i 项的值。
|
||||
- 转移:dp[i] = dp[i-1] + dp[i-2]。
|
||||
- 边界:dp[0] = 0, dp[1] = 1。
|
||||
- 示例代码:
|
||||
```python
|
||||
def fib(n):
|
||||
if n <= 1:
|
||||
return n
|
||||
dp = [0] * (n + 1)
|
||||
dp[1] = 1
|
||||
for i in range(2, n + 1):
|
||||
dp[i] = dp[i-1] + dp[i-2]
|
||||
return dp[n]
|
||||
# 示例:fib(5) = 5
|
||||
```
|
||||
- **最长递增子序列 (LIS)**:给定数组,求最长递增子序列的长度。
|
||||
- 状态:dp[i] 表示以第 i 个元素结尾的最长递增子序列长度。
|
||||
- 转移:dp[i] = max(dp[j] + 1) for j < i and nums[j] < nums[i]。
|
||||
- 边界:dp[i] = 1。
|
||||
|
||||
#### 2. **区间 DP**
|
||||
- **定义与特点**:问题涉及合并或处理区间(如数组的子区间),通常枚举区间的长度和起点,从小区间向大区间递推。状态是二维数组 dp[l][r],表示区间 [l, r] 的最优值。
|
||||
- **适用场景**:区间合并、括号匹配等。
|
||||
- **例子**:
|
||||
- **矩阵链乘法**:给定 n 个矩阵的维度,求最小乘法次数。
|
||||
- 状态:dp[i][j] 表示从第 i 到第 j 个矩阵的最小乘法次数。
|
||||
- 转移:dp[i][j] = min(dp[i][k] + dp[k+1][j] + dims[i-1]*dims[k]*dims[j]) for k in [i, j-1]。
|
||||
- 边界:dp[i][i] = 0。
|
||||
- 示例:矩阵尺寸 [10, 30, 5, 60],最小乘法次数为 7500。
|
||||
- **石子合并**:n 堆石子合并成一堆的最小成本(相邻堆合并成本为石子数和)。
|
||||
- 状态:dp[i][j] 表示合并 [i, j] 堆的最小成本。
|
||||
- 转移:类似矩阵链乘法。
|
||||
|
||||
#### 3. **树形 DP**
|
||||
- **定义与特点**:在树结构上进行 DP,通常从叶子节点向上递推。状态定义在树节点上,可能包括子树的信息。常用 DFS 实现。
|
||||
- **适用场景**:树上的路径、覆盖、独立集等问题。
|
||||
- **例子**:
|
||||
- **树上最大独立集**:在树中选节点,使无相邻节点被选,且节点权值和最大。
|
||||
- 状态:dp[u][0] 表示不选 u 的最大值;dp[u][1] 表示选 u 的最大值。
|
||||
- 转移:dp[u][0] = sum(max(dp[v][0], dp[v][1]) for v in children);dp[u][1] = weight[u] + sum(dp[v][0] for v in children)。
|
||||
- 边界:叶子节点 dp[u][0] = 0, dp[u][1] = weight[u]。
|
||||
- **树的最长路径**:求树中任意两节点的最长路径长度。
|
||||
|
||||
#### 4. **状态压缩 DP**
|
||||
- **定义与特点**:当状态数量不多时,用二进制位表示集合状态(比特位 DP)。状态通常是 dp[mask] 或 dp[i][mask],mask 表示子集。
|
||||
- **适用场景**:组合优化,如子集问题,状态数不超过 2^20。
|
||||
- **例子**:
|
||||
- **旅行商问题 (TSP)**:从起点访问所有城市并返回的最短路径。
|
||||
- 状态:dp[mask][u] 表示访问过 mask 集合的城市,最后在 u 的最小距离。
|
||||
- 转移:dp[mask][u] = min(dp[mask - {u}][v] + dist[v][u]) for v != u。
|
||||
- 边界:dp[1<<start][start] = 0。
|
||||
- **Hamilton 路径**:求图中访问所有节点一次的路径。
|
||||
|
||||
#### 5. **数位 DP**
|
||||
- **定义与特点**:处理数字的每一位,从高位到低位递推。状态包括当前位置、是否紧界(是否等于上限)、其他属性(如和的模)。
|
||||
- **适用场景**:统计 [1, n] 内满足条件的数字个数。
|
||||
- **例子**:
|
||||
- **统计 [1, n] 内不含 49 的数字个数**。
|
||||
- 状态:dp[pos][tight][has49] 表示从高位到 pos 位,tight 是否等于 n 的前缀,has49 是否已出现 49。
|
||||
- 转移:枚举当前位 d,更新下一位状态。
|
||||
- 边界:从最高位开始。
|
||||
|
||||
#### 6. **背包 DP**
|
||||
- **定义与特点**:经典优化问题,状态表示容量和物品选择。通常一维或二维数组,优化空间。
|
||||
- **适用场景**:资源分配、组合优化。
|
||||
- **例子**:
|
||||
- **01 背包**:n 物品,容量 V,求最大价值(每个物品选或不选)。
|
||||
- 状态:dp[i][v] 表示前 i 物品,容量 v 的最大价值。
|
||||
- 转移:dp[i][v] = max(dp[i-1][v], dp[i-1][v - w[i]] + val[i]) if v >= w[i]。
|
||||
- 优化:一维 dp[v] = max(dp[v], dp[v - w[i]] + val[i])(逆序)。
|
||||
- **完全背包**:物品无限选,转移正序。
|
||||
|
||||
#### 7. **概率 DP**
|
||||
- **定义与特点**:涉及概率计算,状态表示期望值或概率。转移基于概率加权。
|
||||
- **适用场景**:随机过程、游戏期望。
|
||||
- **例子**:
|
||||
- **扔硬币期望**:扔 n 次硬币,求达到 k 个正面的期望扔次数。
|
||||
- 状态:dp[i] 表示已有 i 个正面的期望剩余扔次数。
|
||||
- 转移:dp[i] = 1 + 0.5 * dp[i+1] + 0.5 * dp[i](需解方程)。
|
||||
|
||||
#### 8. **博弈 DP**
|
||||
- **定义与特点**:两人博弈,状态表示当前局面下的最优值(胜负或分数)。常用 min-max。
|
||||
- **适用场景**:游戏、Nim 堆等。
|
||||
- **例子**:
|
||||
- **Nim 游戏**:多堆石子,两人轮流取,求先手是否必胜。
|
||||
- 状态: Grundy 值(异或所有堆的 mex 值)。
|
||||
- **取石子游戏**:一堆石子,每次取 1~m 个,最后取者胜。
|
||||
|
||||
这些分类不是严格互斥的,有些问题可以归入多个类别(如背包可视为线性 DP)。在实际问题中,选择分类取决于问题结构。建议从简单线性 DP 开始练习,如 LeetCode 的 DP 专题。如果你有特定问题或需要代码实现某个例子,请提供更多细节!
|
||||
31
Algorithm/DP-DynamicProgramming/Linear-DP/AT_dp_f LCS.cpp
Normal file
31
Algorithm/DP-DynamicProgramming/Linear-DP/AT_dp_f LCS.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
int main(){
|
||||
string a, b;
|
||||
cin >> a >> b;
|
||||
int a_size = a.size(), b_size = b.size();
|
||||
vector<vector<pair<int, string>>> dp(a.size() + 1, vector<pair<int, string>>(b_size + 1, {0, ""}));
|
||||
for(int i = 1; i <= a_size; i++){
|
||||
for(int j = 1; j <= b_size; j++){
|
||||
if(a[i - 1] == b[j - 1]) {
|
||||
dp[i][j].first = dp[i - 1][j - 1].first + 1;
|
||||
string tmp = dp[i - 1][j - 1].second;
|
||||
tmp.push_back(a[i - 1]);
|
||||
dp[i][j].second = tmp;
|
||||
}
|
||||
else{
|
||||
dp[i][j].first = max(dp[i - 1][j].first, dp[i][j - 1].first);
|
||||
if(dp[i - 1][j].first > dp[i][j - 1].first){
|
||||
dp[i][j].second = dp[i - 1][j].second;
|
||||
}
|
||||
else dp[i][j].second = dp[i][j - 1].second;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//cout << dp[a_size][b_size].first << " " << dp[a_size][b_size].second << endl;
|
||||
cout << dp[a_size][b_size].second << endl;
|
||||
return 0;
|
||||
}
|
||||
28
Algorithm/DP-DynamicProgramming/Linear-DP/B3637 最长上升子序列.cpp
Normal file
28
Algorithm/DP-DynamicProgramming/Linear-DP/B3637 最长上升子序列.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
struct cmp{
|
||||
bool operator()(const pair<int, int>& a, const pair<int, int>& b){
|
||||
if(a.first != b.first) return a.first > b.first;
|
||||
return a.second < b.second;
|
||||
}
|
||||
};
|
||||
int main(){
|
||||
int n;
|
||||
cin >> n;
|
||||
vector<int> a(n);
|
||||
for(int i = 0; i < n; i++){
|
||||
cin >> a[i];
|
||||
}
|
||||
//dp[i]-><3E><><EFBFBD><EFBFBD>ǰi<C7B0><69><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB3A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> pair(<28><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>ֵ)
|
||||
vector<int> dp(n, 1);
|
||||
for(int i = 0; i < n; i++){
|
||||
for(int j = 0; j < i; j++){
|
||||
if(a[i] > a[j]) dp[i] = max(dp[i], dp[j] + 1);
|
||||
}
|
||||
}
|
||||
int m = *max_element(dp.begin(), dp.end());
|
||||
cout << m << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
int main(){
|
||||
int len, n;
|
||||
cin >> len >> n;
|
||||
vector<int> a(n + 2);
|
||||
vector<vector<int>> dp(n + 2, vector<int>(n + 2, 0));
|
||||
//<2F><><EFBFBD><EFBFBD>dp[i][j]Ϊ<>и<EFBFBD>ľ<EFBFBD><C4BE>[i, j]<5D><> 0|---1|-----2|----3|--4| <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD> a[0] = 0 a[1] = x,,, a[n + 1] = len
|
||||
a[0] = 0; a[n + 1] = len;
|
||||
for(int i = 1; i <= n; i++){
|
||||
cin >> a[i];
|
||||
}
|
||||
//a[i]<5D>Ƿֵ<C7B7>
|
||||
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
for(int i = 0; i <= n + 1; i++){
|
||||
for(int j = i; j <= n + 1 ;j++){
|
||||
dp[i][j] = 114514;
|
||||
for(int k = i + 1; k < j; k++){
|
||||
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + a[j] - a[i]);
|
||||
}
|
||||
if(dp[i][j] == 114514) dp[i][j] = 0;
|
||||
}
|
||||
} */
|
||||
// <20><><EFBFBD><EFBFBD> DP<44><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><C8B5><EFBFBD>
|
||||
for(int l = 2; l <= n + 1; l++){ // <20><><EFBFBD>䳤<EFBFBD><E4B3A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2
|
||||
for(int i = 0; i + l <= n + 1; i++){
|
||||
int j = i + l;
|
||||
dp[i][j] = INT_MAX;
|
||||
for(int k = i + 1; k < j; k++){
|
||||
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + a[j] - a[i]);
|
||||
}
|
||||
if(dp[i][j] == INT_MAX) dp[i][j] = 0;
|
||||
}
|
||||
}
|
||||
cout << dp[0][n + 1] << endl;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
int main(){
|
||||
ios::sync_with_stdio(false);
|
||||
cin.tie(nullptr);
|
||||
|
||||
int T;
|
||||
if(!(cin >> T)) return 0;
|
||||
while(T--){
|
||||
string s;
|
||||
cin >> s;
|
||||
int n = s.size();
|
||||
if(n == 0){
|
||||
cout << 0 << "\n";
|
||||
continue;
|
||||
}
|
||||
// isPal[i][j] whether s[i..j] is palindrome
|
||||
vector<vector<char>> isPal(n, vector<char>(n, 0));
|
||||
// center expand to fill isPal (or use DP)
|
||||
for(int center = 0; center < n; ++center){
|
||||
// odd length
|
||||
int l = center, r = center;
|
||||
while(l >= 0 && r < n && s[l] == s[r]){
|
||||
isPal[l][r] = 1;
|
||||
--l; ++r;
|
||||
}
|
||||
// even length
|
||||
l = center; r = center + 1;
|
||||
while(l >= 0 && r < n && s[l] == s[r]){
|
||||
isPal[l][r] = 1;
|
||||
--l; ++r;
|
||||
}
|
||||
}
|
||||
|
||||
// dp[i] = min cuts for s[0..i]
|
||||
const int INF = 1e9;
|
||||
vector<int> dp(n, INF);
|
||||
for(int i = 0; i < n; ++i){
|
||||
if(isPal[0][i]){
|
||||
dp[i] = 0;
|
||||
} else {
|
||||
for(int j = 0; j < i; ++j){
|
||||
if(isPal[j+1][i]){
|
||||
dp[i] = min(dp[i], dp[j] + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cout << dp[n-1] << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
const int INF = 1e9;
|
||||
bool match(char a, char b){
|
||||
return (a == '(' && b == ')') || (a == '[' && b == ']');
|
||||
}
|
||||
int main(){
|
||||
string s;
|
||||
cin >> s;
|
||||
int n = s.size();
|
||||
vector<vector<int>> dp(s.size() + 2, vector<int>(s.size() + 2, 1));
|
||||
for(int l = 2; l <= n; l++){
|
||||
for(int i = 0; i < n - l + 1; i++){
|
||||
int j = i + l - 1;
|
||||
dp[i][j] = INF;
|
||||
for(int k = i; k < j; k++){
|
||||
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
|
||||
}
|
||||
if(match(s[i], s[j])) {
|
||||
if (i + 1 <= j - 1)
|
||||
dp[i][j] = min(dp[i][j], dp[i+1][j-1]);
|
||||
else
|
||||
dp[i][j] = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ƥ<EFBFBD><C6A5>
|
||||
}
|
||||
}
|
||||
}
|
||||
cout << dp[0][n - 1] << endl;
|
||||
return 0;
|
||||
}
|
||||
28
Algorithm/DP-DynamicProgramming/Linear-DP/P1439.cpp
Normal file
28
Algorithm/DP-DynamicProgramming/Linear-DP/P1439.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
int main(){
|
||||
int n;
|
||||
cin >> n;
|
||||
vector<int> a(n), b(n);
|
||||
for(int i = 0; i < n; i++){
|
||||
cin >> a[i];
|
||||
}
|
||||
for(int i = 0; i < n; i++){
|
||||
cin >> b[i];
|
||||
}
|
||||
int a_size = a.size(), b_size = b.size();
|
||||
vector<vector<int>> dp(a.size() + 1, vector<int>(b_size + 1, 0));
|
||||
for(int i = 1; i <= a_size; i++){
|
||||
for(int j = 1; j <= b_size; j++){
|
||||
if(a[i - 1] == b[j - 1]) {
|
||||
dp[i][j] = dp[i - 1][j - 1] + 1;
|
||||
}
|
||||
else{
|
||||
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
cout << dp[a_size][b_size] << endl;
|
||||
return 0;
|
||||
}
|
||||
50
Algorithm/DP-DynamicProgramming/Tree-DP/树的最大独立集.cpp
Normal file
50
Algorithm/DP-DynamicProgramming/Tree-DP/树的最大独立集.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
void dfs(vector<vector<int>>& d, const vector<vector<int>>& adj_, vector<bool>& vs, int v){
|
||||
d[v][0] = 0;
|
||||
d[v][1] = 1;
|
||||
for(auto x : adj_[v]){
|
||||
if(vs[x] == false) {
|
||||
vs[x] = true;
|
||||
dfs(d, adj_, vs, x);
|
||||
//<2F><><EFBFBD><EFBFBD>
|
||||
d[v][0] += max(d[x][0], d[x][1]); // <20><>ѡu<D1A1><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ
|
||||
d[v][1] += d[x][0]; // ѡu<D1A1><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>벻ѡ<EBB2BB><D1A1>
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(){
|
||||
//ͼ<>Ļ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>vector<6F><72><EFBFBD>ڽӱ<DABD><D3B1><EFBFBD><EFBFBD><EFBFBD>
|
||||
int n;
|
||||
cin >> n;
|
||||
vector<vector<int>> adj(n);
|
||||
vector<vector<int>> dp(n, vector<int>(2, 0));
|
||||
vector<bool> visited(n, false);
|
||||
//vector<vector<int>> choose(n, vector<int>(n, 0));
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>0<EFBFBD><30>ʼ<EFBFBD><CABC>n - 1
|
||||
for(int i = 0; i < n - 1; i++){
|
||||
int a, b;
|
||||
cin >> a >> b;
|
||||
adj[a].push_back(b);
|
||||
adj[b].push_back(a);
|
||||
}
|
||||
/*
|
||||
for(int l = 2; l <= n; l++){
|
||||
for(int i = 0; i < n - l + 1; i++){
|
||||
int j = i + l - 1;
|
||||
for(int k = i; k < j; k++){
|
||||
if(adj[i][j])
|
||||
d[i][j] = max(dp[i][j], )
|
||||
}
|
||||
}
|
||||
}*/
|
||||
visited[0] = true;
|
||||
dfs(dp, adj, visited, 0); // <20><>0Ϊ<30><CEAA>
|
||||
cout << max(dp[0][0], dp[0][1]) << endl;
|
||||
return 0;
|
||||
}
|
||||
60
Algorithm/DP-DynamicProgramming/Tree-DP/树的直径-最远点对.cpp
Normal file
60
Algorithm/DP-DynamicProgramming/Tree-DP/树的直径-最远点对.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
vector<vector<int>> adj;
|
||||
vector<int> dp;
|
||||
void dfs(int v, int parent){
|
||||
//no return;
|
||||
for(auto x : adj[v]){
|
||||
if(x == parent) continue;
|
||||
dfs(x, v);
|
||||
dp[v] = max(dp[v], dp[x] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
int n;
|
||||
cin >> n;
|
||||
adj.resize(n, vector<int>());
|
||||
dp.resize(n, 1);
|
||||
vector<bool> visited(n, false);
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>0<EFBFBD><30>ʼ<EFBFBD><CABC>n - 1
|
||||
for(int i = 0; i < n - 1; i++){
|
||||
int a, b;
|
||||
cin >> a >> b;
|
||||
adj[a].push_back(b);
|
||||
adj[b].push_back(a);
|
||||
}
|
||||
dfs(0, -1);
|
||||
int mmax = 0;
|
||||
if(adj[0].size() == 1) cout << dp[0] << endl;
|
||||
else{
|
||||
vector<int> tmp;
|
||||
for(auto x : adj[0]){
|
||||
tmp.push_back(dp[x]);
|
||||
}
|
||||
sort(tmp.begin(), tmp.end());
|
||||
mmax = *(tmp.end() - 1) + *(tmp.end() - 2);
|
||||
cout << mmax + 1<< endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
7
|
||||
0 1
|
||||
0 2
|
||||
1 3
|
||||
1 4
|
||||
2 5
|
||||
2 6
|
||||
|
||||
8
|
||||
0 1
|
||||
0 2
|
||||
1 3
|
||||
1 4
|
||||
2 5
|
||||
2 6
|
||||
3 7
|
||||
*/
|
||||
Binary file not shown.
69
Algorithm/Recursion/P1044 [NOIP 2003 普及组] 栈.cpp
Normal file
69
Algorithm/Recursion/P1044 [NOIP 2003 普及组] 栈.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <deque>
|
||||
using namespace std;
|
||||
set<deque<int>> result;
|
||||
void dfs(deque<int>& path, deque<int>& stack, deque<int>& left){
|
||||
if(stack.size() == 0 && left.size() == 0){
|
||||
result.emplace(path);
|
||||
return;
|
||||
}
|
||||
else if(stack.size() == 0){
|
||||
int tmp = left.front();
|
||||
stack.push_back(tmp);
|
||||
left.pop_front();
|
||||
dfs(path, stack, left);
|
||||
left.push_front(tmp);
|
||||
stack.pop_back();
|
||||
}
|
||||
else if(left.size() == 0){
|
||||
int tmp = stack.back();
|
||||
stack.pop_back();
|
||||
path.push_back(tmp);
|
||||
dfs(path, stack, left);
|
||||
stack.push_back(tmp);
|
||||
path.pop_back();
|
||||
}
|
||||
else {
|
||||
{
|
||||
int tmp = left.front();
|
||||
left.pop_front();
|
||||
stack.push_back(tmp);
|
||||
dfs(path, stack, left);
|
||||
stack.pop_back();
|
||||
left.push_front(tmp);
|
||||
}
|
||||
{
|
||||
int tmp = stack.back();
|
||||
stack.pop_back();
|
||||
path.push_back(tmp);
|
||||
dfs(path, stack, left);
|
||||
path.pop_back();
|
||||
stack.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(){
|
||||
int n;
|
||||
cin >> n;
|
||||
deque<int> l(n), s, p;
|
||||
for(int i = 0; i < n; i++){
|
||||
l[i] = i + 1;
|
||||
}
|
||||
dfs(p, s, l);
|
||||
cout << result.size() << endl;
|
||||
/*
|
||||
for(auto x : result){
|
||||
for(auto y : x){
|
||||
cout << y << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}*/
|
||||
for(auto x : *result.begin()){
|
||||
cout << x << " ";
|
||||
}
|
||||
cout << endl;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user