SGU221-动态规划

题意:给定n*n的棋盘,放置k个象的方案数。象的攻击为对角线。

黑书p243例题

总结:

dp,有的时候可以把阶段排序,这样分阶段,可以减少状态表示。

技巧,mark!

另外sgu上很多题目都是用大数啊,这里贴了个大数的模板。

#include<stdio.h>
#include<string.h>
#include<math.h>
#define LL long long
#define M 55
#define N 2555
#define base 10000

struct bign{
    int l,a[M];
    bign(){
        memset(a,0,sizeof(a)); l = 0;
    }
    bign(int x){
        memset(a,0,sizeof(a));
        for(l= 0; x; x/= base)
            a[l++] = x%base;
        if(!l) l++;
    }
    bign operator = (bign x){
        memcpy(a,x.a,sizeof(a));
        l = x.l;
        return *this;
    }
    bign operator + (bign x){
        bign res; int i,cy = 0;
        for(i = 0; i<l||i<x.l||cy > 0; i++){
            if(i < l) cy += a[i];
            if(i < x.l) cy += x.a[i];
            res.a[i] = cy %base;
            cy /= base;
        }
        res.l = i;
        return res;
    }

    bign operator *(bign x){
        bign res; res.l = 0;
        if(0 == x.l){
            res.a[0] = 0; x.l = 1; return res;
        }
        for(int i = 0; i < l; i++)
            for(int j = 0,cy = 0; j <x.l||cy>0; j++,cy/=base){
                if(j < x.l) cy += a[i]*x.a[j];
                if(i+j < res.l) cy += res.a[i+j];
                if(i+j >= res.l)
                    res.a[res.l++] = cy%base;
                else res.a[i+j] = cy%base;
            }
        return res;
    }
    void print(){
        int i;
        printf("%d",l==0?0:a[l-1]);
        for(i = l-2; i >= 0; i--)
            printf("%04d",a[i]);
        printf("\n");
    }
};
bign dpb[M][N],dpw[M][N];


int n,m;
int w[M],b[M];
int wn,bn;
int main()
{
    int i,j;
    scanf("%d%d",&n,&m);
    wn = bn = 0;
    for (i=1;i<n;i+=2){
        w[++wn] = i;
        w[++wn] = i;
    }
    if (i == n)
        w[++wn] = n;


    for (i=2;i<n;i+=2){
        b[++bn] = i;
        b[++bn] = i;
    }
    if (i==n){
        b[++bn] = n;
    }
/*
    for (int i=1;i<=wn;i++){
        printf("%d %d\n",i,w[i]);
    }
    for (int i=1;i<=bn;i++)
    {
        printf("%d %d\n",i,b[i]);
    }
*/
    dpw[0][0] = 1;
    for (i=1;i<=wn;i++){
        dpw[i][0] = 1;
        for (j=1;j<=w[i];j++)
        {
            dpw[i][j] = dpw[i-1][j] + dpw[i-1][j-1]*bign(w[i] - j +1);
        }
    }

    dpb[0][0] = 1;
    for (i=1;i<=bn;i++){
        dpb[i][0] = 1;
        for (j=1;j<=b[i];j++){
            dpb[i][j] = dpb[i-1][j] + dpb[i-1][j-1]*bign(b[i] - j + 1);
        }
    }

    bign ans = bign(0);
    for (int i=0;i<=m;i++){
        ans = ans + dpw[wn][i]*dpb[bn][m-i];
    }
    ans.print();
    return 0;
}
sgu221

 

转载于:https://www.cnblogs.com/wangsouc/articles/3258505.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值