[USACO16DEC]Team Building团队建设
动态规划
题解:
先排序。
设f[i][j][k].
从f[i][j-1][k],f[i-1][j][k],f[i-1][j-1][k-1](a[i]>b[j])
但是前两种途径有重复的:f[i-1][j-1][k]被加了两遍,减掉。
Code:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
const int mod = 1e9+9;
const int N = 1005;
int n,m,num,a[N],b[N],f[N][N][15];
void upd(int &a,int b){ a=((a+b)%mod+mod)%mod; }
int main(){
freopen("a.in","r",stdin);
scanf("%d%d%d",&n,&m,&num);
for(int i=1;i<=n;i++) scanf("%d",a+i);
for(int i=1;i<=m;i++) scanf("%d",b+i);
sort(a+1,a+1+n); sort(b+1,b+1+m);
for(int i=0;i<=n;i++) f[i][0][0]=1;
for(int i=0;i<=m;i++) f[0][i][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=0;k<=num;k++){
upd(f[i][j][k],f[i-1][j][k]);
upd(f[i][j][k],f[i][j-1][k]);
upd(f[i][j][k],-f[i-1][j-1][k]);
if(a[i]>b[j]) upd(f[i][j][k],f[i-1][j-1][k-1]);
// D(i); D(j); D(k); D(f[i][j][k]); E;
}
}
}
printf("%d\n",f[n][m][num]);
}