• 国际象棋



    容斥原理的应用
    小象: UVA 861
    在国际象棋的规定中,象只能从他所在的位置走对角线,如果两只象处于同一斜线上,他们将攻击对方,
    现给定2个数字n和k,在n*n的棋盘放k个不互相攻击放入小象有多少种放法? (1=<n<=8)(1=<k<=65)
    将棋盘的黑格抽出,剩下的白格子旋转45度,压缩,使得所有位于对角线上的棋子位于一行 ,称之为白棋盘
    R_w; 黑棋盘同样处理 R_b
    如果在白格子里放i个棋子,在黑格子里放(k-i)个棋子,则由乘法定理:
    R=R_w(i)*R_b(k-i)
    R[i][j] 代表前i行共放了j个棋子的方法数
    对于第j行,分2种情况,放与不放
    不放: R[i-1][j]种方法
    放: R[i-1][j-1]*(C[i]-(j-1)) 种。(C[i]-(j-1) C[i]代表第i行的棋子数,因为不能同列,不能放在前
    j-1个棋子所在的列)

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=8;
    int w[N+1],b[N+1],R_w[N+1][65],R_b[N+1][65];
    void init_chessboard(int n){   //初始化黑白棋盘
        memset(w,0,sizeof(w));
        memset(b,0,sizeof(b));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if((i+j)&1)   w[(i+j)>>1]++;
                else
                    b[(i+j)>>1]++;
            }
        }
    }
    //递推公式求解: C代表每行的棋盘数目
    void Bishops(int n,int k,int C[N+1],int R[N+1][65]){
        for(int i=0;i<=n;i++)
            R[i][0]=1;
        for(int i=1;i<=k;i++)
            R[0][i]=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=C[i];j++){
                R[i][j]=R[i-1][j]+R[i-1][j-1]*(C[i]-(j-1));
            }
        }
    }
    int main(){
        int n,k;
        while(cin>>n>>k){
            if(n==0&&k==0)   break;
            init_chessboard(n);
            sort(b+1,b+1+n);
            sort(w+1,w+n);  //w比b少一行
            Bishops(n,k,b,R_b);
            Bishops(n,k,w,R_w);
            int ans=0;
            for(int j=0;j<=k;j++)
                ans+=R_b[n][j]*R_w[n-1][k-j];   //拆分之后一个n行,一个n-1行
          cout<<ans<<endl;
        }
        return 0;
    }



  • 相关阅读:
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
    UVa 10534 DP LIS Wavio Sequence
    LA 4256 DP Salesmen
    HDU 2476 区间DP String painter
    HDU 4283 区间DP You Are the One
  • 原文地址:https://www.cnblogs.com/wintersong/p/4945748.html
Copyright © 2020-2023  润新知