[BZOJ 1867][NOI 1999]钉子和小球(DP水题)

142 篇文章 0 订阅
59 篇文章 0 订阅

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=1867

思路

f[i][j] 代表小球落到第 i 行第j个格子上的概率。很容易得到DP方程

f[i+1][j]+=12f[i][j],f[i+1][j+1]+=12f[i][j],(i,j)

f[i+2][j+1]+=f[i][j],(i,j)

f[1][1]=1

然后写个恶心的分数结构体就行了,注意有个坑点:分数在通分时可能爆long long!

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 60

using namespace std;

typedef long long int LL;

LL gcd(LL a,LL b)
{
    if(!b) return a;
    return gcd(b,a%b);
}

struct Fraction
{
    LL up,dn;
    //Fraction(){ up=0,dn=1; } //!!!
    Fraction(LL _up=0,LL _dn=1):up(_up),dn(_dn){}
    void reduction()
    {
        LL t=gcd(up,dn);
        up/=t,dn/=t;
    }
    void print()
    {
        cout<<up<<'/'<<dn;
    }
}f[MAXN][MAXN];

Fraction operator*(Fraction a,Fraction b)
{
    Fraction c=Fraction(a.up*b.up,a.dn*b.dn);
    c.reduction();
    return c;
}

Fraction operator+(Fraction a,Fraction b)
{
    LL t=gcd(a.dn,b.dn);
    Fraction c=Fraction(b.dn/t*a.up+a.dn/t*b.up,a.dn/t*b.dn);
    c.reduction();
    return c;
}

int n,m;
char map[MAXN][MAXN];

char getch()
{
    char ch=getchar();
    while(ch==' '||ch=='\n'||ch=='\r'||ch=='\t') ch=getchar();
    return ch;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++)
            map[i][j]=getch();
    f[1][1]=Fraction(1,1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(map[i][j]=='*')
                f[i+1][j]=f[i+1][j]+f[i][j]*Fraction(1,2),f[i+1][j+1]=f[i+1][j+1]+f[i][j]*Fraction(1,2);
            else
                f[i+2][j+1]=f[i+2][j+1]+f[i][j];
        }
    f[n+1][m+1].print();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值