码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1820 / uva 861 Little Bishops

时间:2017-09-04 09:56:18      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:ttl   clu   turn   oid   map   ini   ret   hdu   stack   

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1820

题意:给你一个n*n的棋盘,让你放k个象,求方法数

 

象的攻击路线是斜的,所以我们可以将棋盘旋转45°,这样攻击路线就成了水平,象就变成了车

之后可以发现,如果将棋盘分为黑白格子,黑白棋子之间是无法互相攻击的,那我们就可以将他们分开考虑

把棋盘处理成2个下面的图形

技术分享

 

设dp[i][j]表示前i行放了j个车的方法数,c[i]表示第i行可以放置的棋子数量,那么转移方程为:

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

需要注意的是c数组应该是增序的,这样才能保证前面的j-1行放了车,对应这一行就有j-1个位

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int N=70;
int n,k;
int c1[N],c2[N],dp1[10][N],dp2[10][N];
void init()//将棋盘分为黑白色,再将棋盘旋转45°
{
    memset(c1,0,sizeof(c1));
    memset(c2,0,sizeof(c2));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if ((i+j)&1)
                c2[(i+j)>>1]++;//第(i+j)/2斜行有几个格子
            else c1[(i+j)>>1]++;
}
void solve(int dp[N][N],int c[N])
{
    for(int i=0;i<=n;i++)
        dp[i][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=c[i];j++)
            dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(c[i]-j+1);
}
int main()
{
    while(scanf("%d%d",&n,&k)&&n+k)
    {
        init();
        sort(c1+1,c1+1+n);
        sort(c2+1,c2+n);
        memset(dp1,0,sizeof(dp1));
        memset(dp2,0,sizeof(dp2));
        solve(dp1,c1);
        solve(dp2,c2);
        int ans=0;
        for(int i=0;i<=k;i++)
            ans+=dp1[n][i]*dp2[n-1][k-i];
        printf("%d\n",ans);
    }
    return 0;
}

  

 

HDU 1820 / uva 861 Little Bishops

标签:ttl   clu   turn   oid   map   ini   ret   hdu   stack   

原文地址:http://www.cnblogs.com/bk-201/p/7472100.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!