问题描述
有下面这样的一个网格棋盘,a,b,c,d表示了对应边长度,也就是对应格子数。
要在这个棋盘上放K个相互不攻击的车,也就是这K个车没有两个车在同一行,也没有两个车在同一列,问有多少种方案。同样只需要输出答案mod 100003后的结果。
输入格式
输入文件place.in的第1行为有5个非负整数a, b, c, d和k。
输出格式
输出文件place.out包括1个正整数,为答案mod 100003后的结果。
样例输入
2 2 2 2 2
样例输出
38
题解
设f[i][j]表示前i行放了j个车的方案数,显然i<=j
对于第i行,有两种情况:放车或不放车。设第i行有x个格子,如果放车,那么前i行放了j-1个车,则第i行可以放的格子数为x-(j-1),根据乘法原理,放车的方案数为f[i-1][j-1]*(x-j+1);如果第i行不放车,那么前i-1行放了j个车,方案数为f[i-1][j-1]。
当i<=b时,f[i][j]=f[i-1][j]+f[i-1][j-1]*(a-j+1)
当b<i<=b+d时,f[i][j]=(f[i-1][j]+f[i-1][j-1]*(a+c-j+1))
初始化怎么办呢?起初我让f[i][0]=1,f[1][1]=a,然而死活算不对,后来我发现只要f[i][1]的值对了,其他的值就对了,所以把f[i][1]初始化一下就行了。
#include <cstdio> const int maxn=100003; int a,b,c,d,n,m,f[2005][1005]; int main() { int i,j,k; scanf("%d%d%d%d%d",&a,&b,&c,&d,&n); m=b+d; for (i=1;i<=b;i++) f[i][1]=a*i; for (i=b+1;i<=m;i++) f[i][1]=a*i+c*(i-b); for (i=2;i<=b;i++) for (j=2;j<=i;j++) f[i][j]=(f[i-1][j]+f[i-1][j-1]*(a-j+1))%maxn; for (i=b+1;i<=m;i++) for (j=2;j<=i;j++) f[i][j]=(f[i-1][j]+f[i-1][j-1]*(a+c-j+1))%maxn; printf("%d",f[m][n]); return 0; }
原文地址:https://www.cnblogs.com/rabbit1103/p/9007385.html
时间: 2024-10-07 05:28:13