118D - Caesars Legions

問題

シーザーは兵士を整列させるのが大好きで、n1人の歩兵とn2人の騎兵を所有しています。彼にはこだわりがあって、k1人より多く歩兵が連続して並んでいたり、k2人より多く騎兵が連続して並んでいるのは、美しくない並び方だと思っています。n1,n2,k1,k2が与えられたとき、シーザーが美しいと思う並べ方の総数を答えなさい。(n1,n2<=100 k1,k2<=10)

解法

dp[n][m][k][l]:=「歩兵をn人,騎兵をm人使って,最後にl人の(歩兵(k=0)or騎兵(k=1))が連続するような並べ方の総数」
と定義すると

  • dp[n+1][m][0][0] = Σdp[n][m][1][l] (l=0,...,k2-1) (1が並んでいるところに0を追加する。)
  • dp[n][m+1][1][0] = Σdp[n][m][0][l] (l=0,...,k1-1) (0が並んでいるところに1を追加する。)
  • dp[n+1][m][0][l+1] = dp[n][m][0][l] (0が並んでいるところに0を追加する)
  • dp[n][m+1][1][l+1] = dp[n][m][1][l] (1が並んでいるところに1を追加する)

が成り立つので、ループを使って計算する。
答えは Σdp[n1][n2][k][l]

コード

int main(){
  int n1,n2,k1,k2;
  cin>>n1>>n2>>k1>>k2;
  int dp[102][102][2][11]={};
  dp[1][0][0][0] = 1;
  dp[0][1][1][0] = 1;
  FOR(i,0,n1+1)FOR(j,0,n2+1)REP(k,10){
    dp[i+1][j][0][0] += dp[i][j][1][k];
    dp[i][j+1][1][0] += dp[i][j][0][k];
    if(k+2 <= k1)dp[i+1][j][0][k+1] += dp[i][j][0][k];
    if(k+2 <= k2)dp[i][j+1][1][k+1] += dp[i][j][1][k];
    dp[i+1][j][0][0] %= MOD;
    dp[i][j+1][1][0] %= MOD;
    dp[i+1][j][0][k+1] %= MOD;
    dp[i][j+1][1][k+1] %= MOD;
  }
  int ans = 0;
  REP(i,2)REP(j,10)ans = (ans+dp[n1][n2][i][j])%MOD;
  cout<<ans<<endl;
  return 0;
}