【Contest Hunter【弱省胡策】Round #0-Flower Dance】组合数学+DP
题目链接:
http://ch.ezoj.tk/contest/%E3%80%90%E5%BC%B1%E7%9C%81%E8%83%A1%E7%AD%96%E3%80%91Round%20%230/Flower%20Dance
题意:
在一个n*m的地图上,两个人同时从左上角走到右下角,其中有一些格子是障碍,不能走。
并且,两个人走的路径不能相交。
求总方案数。
题解:
昨天晚上做这道题一点靠谱的思路都没有。就是不相交路线那里被弄死了。。
后来听了讲解才发现。。代码如此简单!
就是要开动脑筋啊!智商啊!!!
对于两条不相交的路径,那么第一条路径一定是从(1,2)出发,到达(n-1,m);
第二条路径一定是从(2,1)出发,到达(n,m-1);
所以对于一对相交的路径,一定可以从最后一个交点开始按互相交换路径,变为:
第一条路径一定从(1,2)出发,到达(n,m-1);
第二条路径一定从(2,1)出发,到达(n-1,m);
所以,总方案数= 从(1,2)出发到(n-1,m)的方案数 * 从(2,1)出发到达(n,m-1)的方案数 -
从(1,2)出发到达(n,m-1)的方案数 * 从(2,1)出发到达(n-1,m)的方案数。
DP求解即可。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<vector> 6 using namespace std; 7 typedef long long LL; 8 9 const int N=2010,Mod=1000000007; 10 int n,m; 11 char s[N][N]; 12 int a[N][N],b[N][N]; 13 14 int main() 15 { 16 scanf("%d%d",&n,&m); 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%s",s[i]+1); 20 } 21 memset(a,0,sizeof(a)); 22 memset(b,0,sizeof(b)); 23 a[1][1]=b[1][1]=1; 24 for(int i=1;i<=n;i++) 25 for(int j=1;j<=m;j++) 26 if(s[i][j]!='1') 27 { 28 if(i!=1) 29 a[i][j]=(a[i-1][j]+a[i][j-1])%Mod; 30 if(j!=1) 31 b[i][j]=(b[i-1][j]+b[i][j-1])%Mod; 32 } 33 LL x=a[n][m-1],y=b[n-1][m],xx=a[n-1][m],yy=b[n][m-1]; 34 printf("%lld\n",((x*y)%Mod - (xx*yy)%Mod + Mod)%Mod); 35 return 0; 36 }