[BZOJ 1867][NOI 1999]釘と小球(DP水題)
4642 ワード
タイトルリンク
http://www.lydsy.com/JudgeOnline/problem.php?id=1867
構想
小球がi行目j格子に落ちる確率をf[i][j]で表す.DP方程式が簡単に得られる
f[i+1][j]+=12 f[i][j],f[i+1][j+1]+=12 f[i][j],(i,j)は釘
f[i+2][j+1]+=f[i][j],(i,j)はスペース
f[1][1]=1
それから気持ち悪い点数構造体を書けばいいです.穴があることに注意してください.点数は通分時にlong longを爆発させる可能性があります.
コード#コード#
http://www.lydsy.com/JudgeOnline/problem.php?id=1867
構想
小球がi行目j格子に落ちる確率をf[i][j]で表す.DP方程式が簡単に得られる
f[i+1][j]+=12 f[i][j],f[i+1][j+1]+=12 f[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=='
'||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;
}