• UVA 861 Little Bishops


    https://vjudge.net/problem/UVA-861

    题意:

    在n*n棋盘上方k个互不攻击的象,求方案数

    若两个象在同意对角线上,则会互相攻击

    将棋盘黑白染色,则黑格不会攻击白格,白格不会攻击黑格

    所以黑白格分开考虑

    最终答案= Σ 黑格放i个*白格放k-i个

    将所有黑格抽离出来,旋转45°

    这样对角线方向就变成了水平方向和竖直方向

    问题转化成了 每一行每一列至多放1个

    在按每行格子数量从小到大排序

    这样每行依次为 2个、2个、4个、4个、6个、6个、8个、8个……

    或者每行一次为 1个、1个、3个、3个、5个、5个、7个、7个……

    dp[i][j] 表示前i行放了j个的方案数

    如果第i行不放,就是dp[i-1][j]

    如果第i行放,有j-1列在前i-1行放过了,所以第i行有 该行格数-(j-1)个 位置可以放,就是 dp[i-1][j-1]*(sum-j+1)

    用s[i]表示第i行有多少格子

    dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(s[i]-j+1)

    这样就求出只有黑格或者只有白格的情况,再合并即可

    vjudge一直在pending,先把代码粘上吧。。。。。。

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    #define N 9
    typedef long long LL;
    
    int b[N],w[N]; 
    LL f[N][N],g[N][N]; 
    
    void solve(int n,int k,int s[N],LL dp[N][N])
    {
        memset(dp,0,sizeof(dp));
        for(int i=0;i<=n;++i) dp[i][0]=1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=k && j<=i;++j)
                dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(s[i]-j+1); 
    }
    
    int main()
    {
        int n,k;
        LL ans;
        b[1]=2;
        for(int i=2;i<=8;++i)
            if(i&1) b[i]=b[i-1]+2;
            else b[i]=b[i-1];
        w[1]=1;
        for(int i=2;i<=8;++i)
            if(i&1) w[i]=w[i-1]+2;
            else w[i]=w[i-1];            
        while(1)
        {
            scanf("%d%d",&n,&k);
            if(!n && !k) return 0; 
            solve(n-1,k,b,f);
            solve(n,k,w,g);
            ans=0;
            for(int i=0;i<=k;++i) 
                if(i<=n && k-i<=n) ans+=f[n-1][i]*g[n][k-i];
            printf("%lld
    ",ans);
        }
    }
             
  • 相关阅读:
    贾鹏芳 二胡演奏家
    php 关于下载中文文件实现
    Android 线程。。
    Hadoop命令行接口运行自己编写的类
    ubuntu下jdk环境变量的设置
    navicat导入sql语句文件失败原因-----datetime
    sql server获取当前时间到秒级和毫秒级的语句
    sql关于group by的问题
    java的equal和==的区别
    win8.1 占用80端口问题
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12244188.html
Copyright © 2020-2023  润新知