题意:受伤的皇后只能攻击它这一列的,和它周围的九个格子,题目给出一个字符串,如果第i个字符是?则表示皇后能放在任意位置,如果不是?则表示它指定了必须放在哪一行。问有几种放法。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define LL long long
const int N=20;
bool vis[N][N];
int n,flag[N][N];
char str[N];
LL map[N][N],dp(int,int);
int fun(char);
void add_flag(int,int);
void dele_flag(int,int);
int iabs(int a){return a>0?a:-a;}
bool ch(int,int);
int main()
{
while(scanf("%s",str)!=EOF)
{
bool isend=0;
memset(flag,0,sizeof(flag));
memset(vis,0,sizeof(vis));
memset(map,0,sizeof(map));
n=strlen(str);
int pre=-100;
for(int i=0;i<n;i++)
{
if(str[i]!='?')
{
int temp=fun(str[i]);
if(iabs(temp-pre)<=1) {isend=1;break;}
add_flag(temp,i);
pre=temp;
}
else pre=-100;
}
if(isend) puts("0");
else printf("%lld\n",dp(0,n));
}
}
LL dp(int x,int y)
{
bool &t_flag=vis[x][y];
LL &res=map[x][y];
if(t_flag) return res;
else if(y==0){t_flag=1;res=1;return res;}
else
{
if(str[y-1]!='?') res+=dp(fun(str[y-1]),y-1);
else
{
for(int i=0;i<n;i++)
{
if(flag[i][y-1]) continue;
add_flag(i,y-1);
res+=dp(i,y-1);
dele_flag(i,y-1);
}
}
t_flag=1;
return res;
}
}
void add_flag(int x,int y)
{
for(int i=-1;i<=1;i++)
{
if(ch(x+i,y-1)&&!flag[x+i][y-1]) flag[x+i][y-1]=y+1;
if(ch(x+i,y+1)&&!flag[x+i][y+1]) flag[x+i][y+1]=y+1;
}
}
void dele_flag(int x,int y)
{
for(int i=-1;i<=1;i++)
{
if(ch(x+i,y-1)&&flag[x+i][y-1]==y+1) flag[x+i][y-1]=0;
if(ch(x+i,y+1)&&flag[x+i][y+1]==y+1) flag[x+i][y+1]=0;
}
}
bool ch(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<n;
}
int fun(char a)
{
if(isdigit(a)) return a-'0'-1;
else return a-'A'+9;
}