题意:给你一个棋盘,棋盘的规格为n*n(n为字符串的长度),要求放n个互不攻击的受伤皇后的总的放法数。受伤皇后的攻击范围是同一列,以及以它为中心的向八个方向延伸的一格。字符串中第i个字符,如果为‘?’,意味着在第i列的皇后可以放在任意一行,如果不是的话就要放在指定的行上面。
思路:递推总的方法数。我们可以逐列放皇后,所以d[i][j]表示第i个皇后放在第j行的摆放种类。
状态转移方程:d[i][j] += d[i - 1][k]; (1 < k <= n && abs(j - k) > 1)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
const int MAXN = 20;
char str[MAXN];
long long d[MAXN][MAXN], ans;
int len;
int change(char c) {
if (isdigit(c))
return c - '0';
if (isalpha(c))
return c - 'A' + 10;
}
void init() {
if (str[0] == '?')
for (int i = 1; i <= len; i++)
d[1][i] = 1;
else
d[1][change(str[0])] = 1;
}
void dp() {
for (int i = 2; i <= len; i++) {
if (str[i - 1] == '?') {
for (int j = 1; j <= len; j++) {
for (int k = 1; k <= len; k++)
if (abs(k - j) > 1)
d[i][j] += d[i - 1][k];
}
}
else {
int cur = change(str[i - 1]);
for (int k = 1; k <= len; k++)
if (abs(k - cur) > 1)
d[i][cur] += d[i - 1][k];
}
}
}
int main() {
while (scanf("%s", str) != EOF) {
len = strlen(str);
memset(d, 0, sizeof(d));
init();
dp();
ans = 0;
for (int i = 1; i <= len; i++)
ans += d[len][i];
printf("%lld\n", ans);
}
return 0;
}