1 专题介绍
本专题用来记录使用迭代加深DFS、双向DFS和IDA*算法求解的问题。
2 训练
题目1:170加成序列
C++代码如下,
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
int n;
int path[N];
bool dfs(int u, int k) {
if (u == k) return path[u - 1] == n;
bool st[N] = {0};
for (int i = u - 1; i >= 0; --i) {
for (int j = i; j >= 0; --j) {
int s = path[i] + path[j];
if (s > n || s <= path[u - 1] || st[s]) continue;
st[s] = true;
path[u] = s;
if (dfs(u + 1, k)) return true;
}
}
return false;
}
int main() {
path[0] = 1;
while (cin >> n, n) {
int k = 1;
while (!dfs(1, k)) k++;
for (int i = 0; i < k; ++i) cout << path[i] << ' ';
cout << endl;
}
return 0;
}
题目2:171送礼物
C++代码如下,
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 1 << 24;
int n, m, k;
int g[50], weights[N];
int cnt = 0;
int ans;
void dfs(int u, int s) {
if (u == k) {
weights[cnt++] = s;
return;
}
if ((LL)s + g[u] <= m) dfs(u + 1, s + g[u]);
dfs(u + 1, s);
}
void dfs2(int u, int s) {
if (u == n) {
int l = 0, r = cnt - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (weights[mid] + (LL)s <= m) l = mid;
else r = mid - 1;
}
if (weights[l] + (LL)s <= m) ans = max(ans, weights[l] + s);
return;
}
if ((LL)s + g[u] <= m) dfs2(u + 1, s + g[u]);
dfs2(u + 1, s);
}
int main() {
cin >> m >> n;
for (int i = 0; i < n; ++i) cin >> g[i];
sort(g, g + n);
reverse(g, g + n);
k = n / 2; //防止n=1时,出现死循环
dfs(0, 0);
sort(weights, weights + cnt);
int t = 1;
for (int i = 1; i < cnt; ++i) {
if (weights[i] != weights[i - 1]) {
weights[t++] = weights[i];
}
}
cnt = t;
dfs2(k, 0);
cout << ans << endl;
return 0;
}
题目3:180排书
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 15;
int n;
int q[N];
int w[5][N];
int f() {
int cnt = 0;
for (int i = 0; i + 1 < n; ++i) {
if (q[i + 1] != q[i] + 1) {
cnt++;
}
}
return (cnt + 2) / 3;
}
bool check() {
for (int i = 0; i + 1 < n; ++i) {
if (q[i + 1] != q[i] + 1) {
return false;
}
}
return true;
}
bool dfs(int depth, int max_depth) {
if (depth + f() > max_depth) return false;
if (check()) return true;
for (int len = 1; len <= n; ++len) {
for (int l = 0; l + len - 1 < n; ++l) {
int r = l + len - 1;
for (int k = r + 1; k < n; ++k) {
memcpy(w[depth], q, sizeof q);
int x, y;
for (x = r + 1, y = l; x <= k; ++x, ++y) q[y] = w[depth][x];
for (x = l; x <= r; ++x, ++y) q[y] = w[depth][x];
if (dfs(depth + 1, max_depth)) return true;
memcpy(q, w[depth], sizeof q);
}
}
}
return false;
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 0; i < n; ++i) cin >> q[i];
int depth = 0;
while (depth < 5 && !dfs(0, depth)) depth++;
if (depth >= 5) puts("5 or more");
else cout << depth << endl;
}
return 0;
}
题目4:181回转游戏
C++代码如下,
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 24;
int q[N];
int op[8][7] = {
{0, 2, 6, 11, 15, 20, 22},
{1, 3, 8, 12, 17, 21, 23},
{10, 9, 8, 7, 6, 5, 4},
{19, 18, 17, 16, 15, 14, 13},
{23, 21, 17, 12, 8, 3, 1},
{22, 20, 15, 11, 6, 2, 0},
{13, 14, 15, 16, 17, 18, 19},
{4, 5, 6, 7, 8, 9, 10}
};
int center[8] = {6, 7, 8, 11, 12, 15, 16, 17};
int opposite[8] = {5, 4, 7, 6, 1, 0, 3, 2};
int path[100];
int f() {
static int sum[4];
memset(sum, 0, sizeof sum);
for (int i = 0; i < 8; ++i) sum[q[center[i]]]++;
int s = 0;
for (int i = 1; i <= 3; ++i) s = max(s, sum[i]);
return 8 - s;
}
bool check() {
for (int i = 1; i < 8; ++i) {
if (q[center[i]] != q[center[0]]) {
return false;
}
}
return true;
}
void operation(int x) {
int t = q[op[x][0]];
for (int i = 0; i < 6; ++i) q[op[x][i]] = q[op[x][i + 1]];
q[op[x][6]] = t;
}
bool dfs(int depth, int max_depth, int last) {
if (depth + f() > max_depth) return false;
if (check()) return true;
for (int i = 0; i < 8; ++i) {
if (opposite[i] == last) continue;
operation(i);
path[depth] = i;
if (dfs(depth + 1, max_depth, i)) return true;
operation(opposite[i]);
}
return false;
}
int main() {
while (scanf("%d", &q[0]), q[0]) {
for (int i = 1; i < N; ++i) scanf("%d", &q[i]);
int depth = 0;
while (!dfs(0, depth, -1)) {
depth++;
}
if (!depth) printf("No moves needed");
for (int i = 0; i < depth; ++i) printf("%c", 'A' + path[i]);
printf("\n%d\n", q[6]);
}
return 0;
}