题目的意思就是要在n * n的棋盘上摆放n个受伤的皇后 (受伤的皇后只能攻击那一列,以及周围8个点);
很明显可以知道,因为皇后会攻击所在列 ,所以必须每一列有一个皇后,且只能有一个.
那么输入的字符串有多长,假设长度为n 就是要在n*n棋盘摆n个皇后.
如果第一个字符是 '?' ,则表示第一列的皇后可以让在任意行.
如果不是? ,那么第一列的皇后就要放在指定行(1 ~ F 表示1 ~ 15),
问有多少种不同的摆法.
如果字符长度为len ;
我们可以用递推.先放第一列.
f[i][j]表示第i个皇后放在第j行有几种摆法.(只考虑 i 行之前的);
如果第一个字符是 ? ,那么我们知道f[0][0] ~f[0][len] 都等于1. 如果第一个字符不是? 那么只有对应的那一个是 1;
现在我们再来放后面的.
如果第 i 个字符是 ? 那么我们可以算f[i][0] ~ f[i][len]的所有值,f[i][j] 就等与 sum ( f[i - 1][k] )(也就是把前面那一列所有的情况加起来 , 当然这里的k 和 j 必须差 1 以上 ,因为只差一行的话会互相攻击到)
如果不是 ? 也就是这一列只能放在固定一行,那么我们只能算出f[i][cur] (cur指定行) ,与上面的算法是一样 sum ( f[i - 1][k] ) ,其他的当然就是0了;
算到最后.我们把f[len - 1][k] (k取 0 到 len - 1)加起来
就是把最后一颗皇后也摆上去,算出值,就是答案..
AC代码:
#include<stdio.h>
#include<string.h>
#define ll long long
const int N = 20;
char str[N];
ll f[N][N];
int row(char c) {
if(c >= '0' && c <= '9')
return c - '0' - 1;
else
return c - 'A' + 9;
}
int main() {
int len;
while(scanf("%s",str) != EOF) {
memset(f , 0 ,sizeof(f));
len = strlen(str);
if(str[0] == '?') {
for (int i = 0 ; i < len ;i++) {
f[0][i] = 1;
}
}
else
f[0][row(str[0])] = 1;
for (int i = 1 ; i < len ;i++) {
if(str[i] != '?') {
ll sum = 0;
for (int k = 0 ; k < len ;k++) {
if(k - row(str[i]) > 1 || row(str[i]) - k > 1)
sum += f[i - 1][k];
}
f[i][row(str[i])] = sum;
continue;
}
for (int j = 0 ; j < len ;j++) {
ll sum = 0;
for (int k = 0 ; k < len ;k++) {
if(k - j > 1 || j - k > 1) {
sum += f[i - 1][k];
}
}
f[i][j] = sum;
}
}
ll res = 0;
for (int i = 0 ; i < len ;i++){
res += f[len - 1][i];
}
printf("%lld\n",res);
}
}