【弱省胡策round0T1&&CF348D】Flower Dance

2015.05.26 15:23 Tue | 23次阅读 | 旧日oi | 固定链接 | 源码

题目大意:给定一个n*m的网格图,有一些点不能走,有两个人从(1,1) to(n,m) ,他们的路径不能相交,求方案数
题解:
这场比赛被虐的好惨…………………………
第二题是后缀自动机什么的完全不会,第3到第7题搞了3个题之后实在搞不下去了,看了下题解放弃了。
也就第一题代码又好写还比较有意思。
这种题总有一种很巧妙的利用对称性的解法。在这道题里,我们先用n^2的时间求出(1,2)和(2,1)到(n-1,m)和(m,n-1)的距离。总的方案数是ans[(1,2)][(n-1,m)]*ans[(2,1)][(n,m-1)],而不合法的方案我们可以这么想,考虑两条路径最后一个相交点,让相交之后双方均往对方的目的地走,也就是让从(1,2)开始的到(n,m-1),从(2,1) 开始的到(n-1,m),并且这两种方案中各自任取一条路径都会有交点,所以答案就是总的情况数-相交情况数了。

我的程序

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
#define mod 1000000007
using namespace std;
int a[2005][2005],n,m;
ll ans1,ans2,ans3,ans4;
ll tmp[2005][2005];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    scanf("%1d",&a[i][j]),a[i][j]^=1;
    if(a[2][1]==0||a[1][2]==0) 
    {
        puts("0");
        return 0;
    }
    tmp[1][1]=1;
    for(int i=2;i<=n;i++)
    for(int j=1;j<=m;j++)
    if(a[i][j]) tmp[i][j]=(tmp[i-1][j]+tmp[i][j-1])%mod;
    ans1=tmp[n][m-1],ans2=tmp[n-1][m];
    memset(tmp,0,sizeof(tmp));
    tmp[1][1]=1;
    for(int i=1;i<=n;i++)
    for(int j=2;j<=m;j++)
    if(a[i][j]) tmp[i][j]=(tmp[i-1][j]+tmp[i][j-1])%mod;
    ans3=tmp[n][m-1],ans4=tmp[n-1][m];
    cout<<(ans1*ans4%mod-ans2*ans3%mod+mod)%mod<<endl;
}```