题意:给出一个n*n的棋盘和k个马,问有多少种放的方法使得马互不相攻击。
题解:首先很容易想到设dp[u][v][i][j]表示前i行,用了j个马,第i行的状态为v,前一行的状态为u。
dp[u][v][i][j]+=dp[i][u][i-1][j-cnt[v]]且v不与i,u冲突。
判冲突的话可以这样,前两行左移1位&当前行,为1则冲突,然后右移一样的。前一行就左右移两位&当前行。
但这样做会爆空间,考虑u,v压到一个int 内,再对行数用滚动数组,再n=8,9,10打表。ps(打表调得我好苦啊);
%%%__debug。
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int MAXS=1025,base=256,MAXN=11,MAXST=70000,MAXK=51;
typedef long long ll;
ll dp[MAXST][2][MAXK];
int lim,tot=0,st[MAXST],cnt[MAXST];
ll list_10[110]={1LL,100LL,4662LL,135040LL,2732909LL,41199404LL,481719518LL,4491423916LL,34075586550LL,213628255072LL,1120204619108LL,4961681221524LL,18715619717199LL,60541371615660LL,168976761361446LL,409191804533576LL,864172675710439LL,1599730843649564LL,2609262108838924LL,3770687313420780LL,4857550050070531LL,5616928666465104LL,5874943705896600LL,5604501518609804LL,4917655076255841LL,3999855946779732LL,3034690618677388LL,2156485957257040LL,1437827591264317LL,899278231344296LL,526753407546620LL,288274613750624LL,146990556682887LL,69626509814580LL,30542906352994LL,12366448408056LL,4604442057431LL,1569983914256LL,487876545370LL,137395261280LL,34831261750LL,7884855000LL,1578162590LL,275861904LL,41455966LL,5246412LL,543534LL,44244LL,2652LL,104LL,2};
ll list_9[82]={1LL,81LL,3016LL,68796LL,1080942LL,12472084LL,110018552LL,762775440LL,4241252429LL,19206532478LL,71707869632LL,222946143752LL,582155146204LL,1286247689414LL,2421159140764LL,3908273840366LL,5446391581062LL,6599640204257LL,7010436668992LL,6589213734278LL,5537849837497LL,4207779106033LL,2920161348852LL,1865346129716LL,1101125592067LL,600730512987LL,302041066250LL,139345014744LL,58692638521LL,22451454400LL,7755194754LL,2403337080LL,663103709LL,161373907LL,34237130LL,6238414LL,957145LL,120334LL,11914LL,872LL,42LL,1};
ll list_8[65]={1LL,64LL,1848LL,32084LL,376560LL,3184708LL,20202298LL,98796304LL,379978716LL,1167053680LL,2897726604LL,5876860140LL,9825415557LL,13660238780LL,15932672964LL,15737653004LL,13304668385LL,9742722088LL,6260518246LL,3574590840LL,1830733371LL,844203844LL,349524138LL,128874944LL,41833846LL,11792736LL,2840224LL,572432LL,93840LL,12004LL,1122LL,68LL,2LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL,0LL};
int hashed(int x,int y)
{
return x*base+y;
}
int get1(int x)
{
int tmp=x,c=0;
while(tmp)
{
if(tmp&1)c++;
tmp>>=1;
}
return c;
}
void init()
{
memset(dp,0,sizeof(dp));
memset(cnt,0,sizeof(cnt));
memset(st,0,sizeof(st));
tot=0;
for(int i=0;i<lim;i++)
for(int j=0;j<lim;j++)
{
if(!((i<<2&j)||(i>>2&j)))
st[tot++]=hashed(i,j);
}
for(int i=0;i<MAXST;i++)cnt[i]=get1(i);
}
void clear(int p,int& k)
{
for(int i=0;i<MAXST;i++)
for(int j=0;j<=k;j++)dp[i][p][j]=0;
}
ll work(int n,int k,int t)
{
lim=1<<n;
init();dp[0][0][0]=1;
int p=1;
for(int i=1;i<=n;i++)
{
clear(p,k);
for(int j=0;j<=k;j++)
{
for(int s=0;s<tot;s++)if(cnt[st[s]]<=k)
{
if(i==1&&st[s]!=0)break;
if(i==2&&st[s]>=base)break;
for(int l=0;l<1<<n;l++)
{
int x=st[s]/base,y=st[s]%base;
if(!((x<<1&l)||(x>>1&l)||(y<<2&l)||(y>>2&l)))
if(j>=cnt[l])
{
ll tmp=dp[st[s]][p^1][j-cnt[l]];
dp[y*base+l][p][j]+=tmp;
}
}
}
}
p^=1;
}
ll ans=0;
for(int i=0;i<tot;i++)
if(cnt[st[i]]<=k)
ans+=dp[st[i]][n&1][k];
return ans;
}
int main()
{
freopen("225.in","r",stdin);
freopen("w.out","w",stdout);
int n,k;
scanf("%d %d",&n,&k);
if(n==10)cout<<list_10[k]<<endl;
else if(n==9)cout<<list_9[k]<<endl;
else if(n==8)cout<<list_8[k]<<endl;
else if(k>MAXK)cout<<0<<endl;
else
printf("%I64d",work(n,k,1));
}