点击打开链接
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const long Mod=1000000007;
const int M=1100;
// 虚拟栈中球的个数 即为至少放入球的个数 使得全消
// 实际栈放一个球和栈顶不同 虚拟栈就增加k-1个球
// 实际栈放一个球和栈顶相同 虚拟栈就减少一个球
long long dp[M][M]; // dp[i][j] 还要放i个球时 虚拟栈有j个球时能消除完毕的方法数
int main()
{
int n,m,h,k; //已经n个 在放m个 h种颜色 k连消
while(cin>>n>>m>>h>>k)
{
memset(dp,0,sizeof(dp));
int total=0; // 已经放n个球时 至少需要放多少个球才能全消除
int pre=0,cur=0;
for(int i=1;i<=n;i++)
{
cin>>cur;
if(cur==pre)
total--;
else
total+=k-1;
pre=cur;
}
if(total>m) //
{
cout<<0<<endl;
continue;
}
dp[m][total]=1;
for(int i=m;i>0;i--)
{
for(int j=0;j<=i;j++)
{
if(i-1>=j+k-1) // 还要放的个数大于虚拟栈中个数才有解
dp[i-1][j+k-1]=(dp[i-1][j+k-1]+dp[i][j]*(j? h-1:h))%Mod; // 放不同的
if(i-1>=j-1)
dp[i-1][j-1]=(dp[i-1][j-1]+dp[i][j])%Mod; //放和栈顶相同
// dp[i][j]= dp[i-1][j-1]+ dp[i-1][j+k-1]*(j? h-1:h)
//得 dp[i-1][j-1]的方法数为 dp[i-1][j-1]+dp[i][j] dp[i][j]选放和栈顶相同的决策
//得 dp[i-1][j+k-1]的方法数为 dp[i-1][j+k-1]+dp[i][j]*(j? h-1:h) dp[i][j] 选放和栈顶不同的决策
}
}
cout<<dp[0][0]<<endl;
}
return 0;
}