SGU 225

来源:互联网 发布:mac版itunes制作铃声 编辑:程序博客网 时间:2024/05/06 03:20

      题意:给出一个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));}

1 0
原创粉丝点击