BZOJ4742 : [Usaco2016 Dec]Team Building

Claris發表於2017-01-06

如果我們將兩個人擁有的牛混在一起,並按照戰鬥力從小到大排序,同時把第一個人選的牛看成$)$,第二個人選的牛看成$($的話,那麼我們會發現一個合法的方案對應了一個長度為$2k$的括號序列。

於是DP即可,$f[i][j][k]$表示考慮了前$i$頭牛,目前選了$j$個左括號,括號序列的字首和為$k$的方案數。

時間複雜度$O(nk^2)$。

 

#include<cstdio>
#include<algorithm>
const int N=2010,M=13,P=1000000009;
int n,m,K,cnt,i,j,k,f[N][M][M];
struct E{int x,y;E(){}E(int _x,int _y){x=_x,y=_y;}}a[N];
inline bool cmp(const E&a,const E&b){return a.x==b.x?a.y<b.y:a.x>b.x;}
inline void up(int&x,int y){x+=y;if(x>=P)x-=P;}
int main(){
  scanf("%d%d%d",&n,&m,&K);
  while(n--)scanf("%d",&k),a[++cnt]=E(k,1);
  while(m--)scanf("%d",&k),a[++cnt]=E(k,-1);
  std::sort(a+1,a+cnt+1,cmp);
  for(f[0][0][0]=i=1;i<=cnt;i++)for(j=0;j<=K;j++)for(k=0;k<=K;k++)if(f[i-1][j][k]){
    up(f[i][j][k],f[i-1][j][k]);
    if(a[i].y>0)up(f[i][j+1][k+1],f[i-1][j][k]);
    else if(k)up(f[i][j][k-1],f[i-1][j][k]);
  }
  return printf("%d",f[cnt][K][0]),0;
}

  

相關文章