1. 程式人生 > >2018.10.20 bzoj1079: [SCOI2008]著色方案(多維dp)

2018.10.20 bzoj1079: [SCOI2008]著色方案(多維dp)

傳送門 dp妙題。 f[a][b][c][d][e][last]f[a][b][c][d][e][last]表示還剩下aa個可以用一次的,還剩下bb個可以用兩次的,還剩下cc個可以用三次的,還剩下ee個可以用四次的,還剩下dd個可以用五次的時候的方案數。 再次強調:狀態真是妙啊。 注意到如果這次選可以用i次的,上一次選的是可以用i+1次的這一次的轉移係數要減1。 因為上一次那種可以用i+1i+1次的這一次只能用ii次了,所以轉移時不能用這一種來轉移。 程式碼:

#include<bits/stdc++.h>
using namespace
std; const int mod=1e9+7; int n,f[16][16][16][16][16][6],cnt[6]; inline int read(){ int ans=0; char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } inline int dfs(int a,int b,int c,int d,int e,int las){ if(~
f[a][b][c][d][e][las])return f[a][b][c][d][e][las]; if(!(a|b|c|d|e))return f[a][b][c][d][e][las]=1; f[a][b][c][d][e][las]=0; if(a)(f[a][b][c][d][e][las]+=(long long)(a-(las==2))*dfs(a-1,b,c,d,e,1)%mod)%=mod; if(b)(f[a][b][c][d][e][las]+=(long long)(b-(las==3))*dfs(a+1,b-1,c,d,e,2)%mod)%=mod; if(
c)(f[a][b][c][d][e][las]+=(long long)(c-(las==4))*dfs(a,b+1,c-1,d,e,3)%mod)%=mod; if(d)(f[a][b][c][d][e][las]+=1ll*(d-(las==5))*dfs(a,b,c+1,d-1,e,4)%mod)%=mod; if(e)(f[a][b][c][d][e][las]+=1ll*e*dfs(a,b,c,d+1,e-1,5)%mod)%=mod; return f[a][b][c][d][e][las]; } int main(){ memset(f,-1,sizeof(f)),scanf("%d",&n); for(int i=1;i<=n;++i)++cnt[read()]; cout<<dfs(cnt[1],cnt[2],cnt[3],cnt[4],cnt[5],0); return 0; }