zoukankan      html  css  js  c++  java
  • HDU 4529 郑厂长系列故事——N骑士问题 状压dp

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4529

    郑厂长系列故事——N骑士问题

    Time Limit: 6000/3000 MS (Java/Others)
    Memory Limit: 65535/32768 K (Java/Others)
    #### 问题描述 > 郑厂长不是正厂长 >   也不是副厂长 >   他根本就不是厂长 >   还是那个腾讯公司的码农 >   一个业余时间喜欢下棋的码农 >    >   最近,郑厂长对八皇后问题很感兴趣,拿着国际象棋研究了好几天,终于研究透了。兴奋之余,坐在棋盘前的他又开始无聊了。无意间,他看见眼前的棋盘上只摆了八个皇后,感觉空荡荡的,恰好又发现身边还有几个骑士,于是,他想把这些骑士也摆到棋盘上去,当然棋盘上的一个位置只能放一个棋子。因为受八皇后问题的影响,他希望自己把这些骑士摆上去之后,也要满足每2个骑士之间不能相互攻击。 >   现在郑厂长想知道共有多少种摆法,你能帮助他吗? > > 骑士的下法: >   每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走“日”字)。可以越子,没有"中国象棋"的"蹩马腿"限制。 #### 输入 > 输入第一行为一个整数T(1<=T<=8),表示有T组测试数据; > 每组数据首先是一个整数N(1<=n<=10),表示要摆N个骑士上去; > 接下来是一个`8*8`的矩阵来描述一个棋盘,`’.’`表示这个位置是空的,`’*’`表示这个位置上已经放了皇后了; > 数据中的初始棋盘保证是一个合法的八皇后摆法。 #### 输出 > 对每组数据,请在一行内输出一个整数,表示合法的方案数。 ####样例输入 > 2 > 1 > *....... > ....*... > .......* > .....*.. > ..*..... > ......*. > .*...... > ...*.... > 2 > *....... > ....*... > .......* > .....*.. > ..*..... > ......*. > .*...... > ...*.... > ####样例输出 > 56 > 1409

    题意

    在摆了8个八皇后的8*8的棋盘上摆放n个骑士,要求任意两个骑士互不攻击的方案数。

    题解

    dp[cur][v][i][j]表示第cur行状态是j,第cur-1行状态是i,摆放了v个骑士的方案数。

    代码

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=10000000000000000LL;
    const double eps=1e-9;
    
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxm=8;
    
    LL dp[2][11][1<<maxm][1<<maxm];
    int sumv[1<<8];
    bool f1[1<<maxm][1<<maxm];
    bool f2[1<<maxm][1<<maxm];
    int arr[maxm];
    int n;
    
    void pre(){
        clr(sumv,0);
        clr(f1,0);
        clr(f2,0);
        rep(i,0,(1<<maxm)){
            rep(j,0,maxm) if(i&(1<<j)){
                sumv[i]++;
            }
            rep(j,0,(1<<maxm)){
                if(i&(j<<2)||i&(j>>2)) f1[i][j]=true;
                if(i&(j<<1)||i&(j>>1)) f2[i][j]=true;
            }
        }
    }
    
    char str[22];
    
    int main() {
        pre();
        int tc;
        scf("%d",&tc);
        while(tc--){
            scf("%d",&n);
            clr(arr,0);
            for(int i=0;i<maxm;i++){
                scf("%s",str);
                rep(j,0,maxm){
                    if(str[j]=='*') arr[i]|=(1<<j);
                }
            }
    
            int pre=0,cur=1;
            clr(dp[cur],0);
            for(int i=0;i<(1<<maxm);i++){
                if(i&arr[0]) continue;
                for(int j=0;j<(1<<maxm);j++){
                    if(j&arr[1]) continue;
                    if(f1[i][j]) continue;
                    if(sumv[i]+sumv[j]>n) continue;
                    dp[cur][sumv[i]+sumv[j]][i][j]++;
                }
            }
    
            for(int t=2;t<maxm;t++){
                swap(pre,cur);
                clr(dp[cur],0);
                for(int k=0;k<(1<<maxm);k++){
                    if(k&arr[t]) continue;
                    for(int j=0;j<(1<<maxm);j++){
                        if(j&arr[t-1]) continue;
                        if(f1[j][k]) continue;
                        for(int i=0;i<(1<<maxm);i++){
                            if(i&arr[t-2]) continue;
                            if(f1[i][j]||f2[i][k]) continue;
                            int w=sumv[k];
                            for(int v=w;v<=n;v++){
                                dp[cur][v][j][k]+=dp[pre][v-w][i][j];
                            }
                        }
                    }
                }
            }
    
            LL ans=0;
            for(int i=0;i<(1<<maxm);i++){
                for(int j=0;j<(1<<maxm);j++){
                    ans+=dp[cur][n][i][j];
                }
            }
    
            prf("%lld
    ",ans);
    
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    一个好的时间函数
    Codeforces 785E. Anton and Permutation
    Codeforces 785 D. Anton and School
    Codeforces 510 E. Fox And Dinner
    Codeforces 242 E. XOR on Segment
    Codeforces 629 E. Famil Door and Roads
    Codeforces 600E. Lomsat gelral(Dsu on tree学习)
    Codeforces 438D The Child and Sequence
    Codeforces 729E Subordinates
    【ATcoder】D
  • 原文地址:https://www.cnblogs.com/fenice/p/6006110.html
Copyright © 2011-2022 走看看