题目大意:
有n个木块排成一行,从左到右依次编号为1~n 有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块
所有油漆刚好足够涂满所有木块,即c1+c2+...+ck==n
统计任意两个相邻木块颜色不同的着色方案
思路:
记忆化dfs
记录剩余1个能涂,2个能涂……的情况以及前一个的颜色
然后这种颜色-1不能被取到,因为上次它被取了,就减了一
其余的正常的dfs转移
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<queue> 8 #include<map> 9 #include<vector> 10 #define ll long long 11 #define inf 2147483611 12 #define MAXN 17 13 #define MOD 1000000007 14 using namespace std; 15 inline ll read() 16 { 17 ll x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 ll n,dp[MAXN][MAXN][MAXN][MAXN][MAXN][7],t[10]; 23 ll dfs(int t1,int t2,int t3,int t4,int t5,int ban) 24 { 25 ll& res=dp[t1][t2][t3][t4][t5][ban]; 26 if(dp[t1][t2][t3][t4][t5][ban]) return dp[t1][t2][t3][t4][t5][ban]; 27 if(t1+t2+t3+t4+t5==0) return 1; 28 if(t1&&ban==2) (res+=(t1-1)*dfs(t1-1,t2,t3,t4,t5,1))%=MOD; 29 if(t1&&ban!=2) (res+=t1*dfs(t1-1,t2,t3,t4,t5,1))%=MOD; 30 if(t2&&ban==3) (res+=(t2-1)*dfs(t1+1,t2-1,t3,t4,t5,2))%=MOD; 31 if(t2&&ban!=3) (res+=t2*dfs(t1+1,t2-1,t3,t4,t5,2))%=MOD; 32 if(t3&&ban==4) (res+=(t3-1)*dfs(t1,t2+1,t3-1,t4,t5,3))%=MOD; 33 if(t3&&ban!=4) (res+=t3*dfs(t1,t2+1,t3-1,t4,t5,3))%=MOD; 34 if(t4&&ban==5) (res+=(t4-1)*dfs(t1,t2,t3+1,t4-1,t5,4))%=MOD; 35 if(t4&&ban!=5) (res+=t4*dfs(t1,t2,t3+1,t4-1,t5,4))%=MOD; 36 if(t5) (res+=t5*dfs(t1,t2,t3,t4+1,t5-1,5))%=MOD; 37 //cout<<t1<<" "<<t2<<" "<<t3<<" "<<t4<<" "<<t5<<" "<<ban<<" "<<res<<" "<<dp[t1][t2][t3][t4][t5][ban]<<endl; 38 return res; 39 } 40 int main() 41 { 42 n=read();ll a; 43 for(int i=1;i<=n;i++) a=read(),t[a]++; 44 printf("%lld",dfs(t[1],t[2],t[3],t[4],t[5],0)); 45 }