HDU 5794

给你一个边界h,w;

有n个障碍物,有障碍物的地方不能走。马走日字,问左上到右下有多少种路径。

做法:dp[i]表示不走过其他点的到这个点的路径数。

所以转移方程就有,这个点的值等于全部路径,减去,在它之前的所有障碍点到这个点的路径。因为对于每一个障碍点,都是第一次到达障碍点,所以后面只要计算全部路径,就一定可以不重不漏。

这道题可能在h,w的地方有个障碍,坑爹呢。。。

#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <stack>
#include <cstdlib>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const long long MOD=110119;
LL all[MOD+5],f[MOD+5];

LL C(LL n, LL m)
{
    if(m > n) return 0;
    if (m==0) return 1;
    if (m<0) return 0;
    return f[n]*all[f[m]]%MOD*all[f[n-m]]%MOD;
}
LL Lucas(LL n, LL m)
{
    if(m == 0) return 1;
    return C(n % MOD, m % MOD) * Lucas(n / MOD, m / MOD) % MOD;
}
void init()
{
    f[1]=f[0]=all[1]=1;
    for(int i=2; i<=MOD; ++i)
    {
        f[i]=f[i-1]*i%MOD;
        all[i]=all[MOD%i]*(MOD-MOD/i)%MOD;
    }
}
LL dp[2010];
struct node
{
    LL x,y;
} point[2010];
LL cmp(node a,node b)
{
    return a.x<b.x;
}
int main()
{
    init();
    LL h,w,n,ncas=1;

//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    while (scanf ("%I64d%I64d%I64d",&h,&w,&n)!=EOF)
    {
        int flag=0;
        memset(dp,0,sizeof(dp));
        LL t1,t2;
        for (int i=0; i<n; ++i)
        {
            scanf ("%I64d%I64d",&t1,&t2);
            if (t1==h&&t2==w) flag=1;
            point[i].x=t1-1;
            point[i].y=t2-1;
        }
        sort(point,point+n,cmp);
        point[n].x=h-1;
        point[n].y=w-1;
        ++n;
        if ((point[n-1].x+point[n-1].y)%3!=0||flag)
        {
            printf ("Case #%I64d: %I64d\n",ncas++,0);
            continue;
        }
        for (int i=0; i<n; i++)
        {
            if ((point[i].x+point[i].y)%3==0)
            {
                LL di=(point[i].x+point[i].y)/3;
                LL gao=min(point[i].x,point[i].y)-di;
                dp[i]=Lucas(di,gao);

                for (int j=0;j<i;j++)
                {
                    if (point[j].y<point[i].y&&point[j].x<point[i].x)
                    {
                        LL xx=point[i].x-point[j].x,yy=point[i].y-point[j].y;
                        if ((xx+yy)%3==0)
                        {
                            LL dd=(xx+yy)/3;
                            LL gg=min(xx,yy)-dd;
                            dp[i]-=(Lucas(dd,gg)*dp[j])%MOD;
                            dp[i]=(dp[i]+MOD)%MOD;
                        }
                    }
                }
            }
        }
        printf ("Case #%I64d: %I64d\n",ncas++,dp[n-1]);
    }
    return 0;
}

 

posted on 2016-08-05 15:46  very_czy  阅读(532)  评论(0编辑  收藏  举报

导航