🍂八皇后
二进制来表示。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <unordered_map>
using namespace std;
int n;
#define MASK(n) ((1<<(n+1))-2) //如 6 得到的是1000 0000 -> 111 1110,零位上的1不用
unordered_map<int, int> ind;
int tot = 3;
int arr[20];
void out()
{
for (int i = 1; i <= n; i++) {
if (i > 1) cout << " ";
printf("%d", arr[i]);
}
printf("\n");
tot--;
return;
}
int dfs(int i, int t1, int t2, int t3)
{
if (i > n) {
if(tot) out();
return 1;
}
int ans = 0;
for (int t = t1; t; t -= (-t & t)) {
int j = ind[-t & t];
if ((t2 & (1 << (i + j - 1))) && (t3 & (1 << (i - j + n)))) //正斜线和反斜线
{
arr[i] = j;
ans += dfs(i + 1, t1^(1 << j), t2^(1 << (i + j - 1)), t3^(1 << (i - j + n))); //把t1中的j标记为0,然后向左移动一位
}
}
return ans;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < 2 * n; i++) ind[1 << i] = i;
int ans = dfs(1, MASK(n), MASK(2 * n - 1), MASK(2 * n - 1)); //列,正斜边,反斜边
cout << ans << "\n";
return 0;
}
🍂奇怪的电梯
思路
先设立两个数组dis[]和to[],分别表示到某层的最少按钮数和按键,dfs(k , a)中k表示使用的按钮数目,a表示到某一层,当dis[]记录到的到某层的最少按钮数小于等于k时,就可递归返回。
比如对于
5 1 5 3 3 1 2 5进行如下优化
#include <iostream>
using namespace std;
const int N = 205;
int to[N];
int dis[N]; //起点到每个点最短距离
int n;
void dfs(int k, int a)
{
if (dis[a] <= k) return;
dis[a] = k; //刷新到a的最短距离
if (a + to[a] <= n) dfs(k + 1, a + to[a]);
if (a - to[a] >= 1) dfs(k + 1, a - to[a]);
}
int main()
{
int a, b;
cin >> n >> a >> b;
for (int i = 1; i <= n; i++) {
cin >> to[i]; //输入每个按钮的值
dis[i] = n + 1;
}
dfs(0, a);
printf("%d\n", dis[b] == n + 1 ? -1 : dis[b]);
return 0;
}
🍂选数
dfs(u,ind,sum)分别表示当前已经选择了几个数,当前这一层可以选择的最小数字,所选当前的和值,is_prime()函数则用来判断是否为质数,这题与之前文章里的【题目/算法训练】全排列相关问题(不用next-permutation)中的组合型枚举很像,想了解的朋友们可以下。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 25;
int a[N];
int n, k;
long long ans = 0; //计算素数的数量
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i++)
{
if (x % i == 0) return false;
}
return true;
}
void dfs(int u,int ind, int sum)
{
if (u == k) {
if (is_prime(sum)) ans++;
return;
}
for(int i = ind; i <= n; i++)
{
dfs(u + 1, i + 1,sum + a[i]);
}
}
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> a[i];
dfs(0, 1, 0);
printf("%lld\n", ans);
return 0;
}