bzoj4742 [Usaco2016 Dec] -- DP

来源:互联网 发布:手机淘宝注册会员名 编辑:程序博客网 时间:2024/05/17 12:25

fi,j,k表示约翰在前i中选k个,保罗在前j个中选k个,约翰打败保罗的方案数,ai表示约翰的第i只牛,bi表示保罗的第i只牛。

就可以列出方程:

fi,j,k=fi1,j,k+fi,j1,kfi1,j1,k+[ai>bj]fi1,j1,k1

其中  fi1,j,k+fi,j1,kfi1,j1,k  表示的是之前的答案。

因为  fi1,j,k+fi,j1,k  重复计算了  fi1,j1,k  的答案,所以要减去 fi1,j1,k 

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 1010#define M 1000000009int a[N],b[N],p,i,j,k,n,m,f[N][N][11];inline int Max(int x,int y){return x<y?y:x;}int main(){    scanf("%d%d%d",&n,&m,&k);    for(i=1;i<=n;i++)scanf("%d",&a[i]);    for(j=1;j<=m;j++)scanf("%d",&b[j]);    for(i=0;i<=n;i++)for(j=0;j<=m;j++)f[i][j][0]=1;    for(i=1;i<=n;i++)    for(j=1;j<=m;j++)    for(p=1;p<=k&&p<=i&&p<=j;p++){        f[i][j][p]=((f[i-1][j][p]+f[i][j-1][p])%M-f[i-1][j-1][p])%M;        if(a[i]>b[j])f[i][j][p]=(f[i][j][p]+f[i-1][j-1][p-1])%M;    }    printf("%d\n",(f[n][m][k]+M)%M);    return 0;}
原创粉丝点击