这题也是看了别人题解也才会做的。
题解:
本题用的记忆优化搜索,题目说了给的颜色可以恰好图够所有木块。
题目给了能涂几块木块的颜色一共有几种。因为我们不可以连续图,所以我们把他分开来涂色。
用dp[a][b][c][d][e][last]
表示能涂a表示的是能涂1个木块颜色还有a个,前一个涂得颜色是last个颜色时方案总数。
表示能涂b表示的是能涂2个木块颜色还有b个,前一个涂得颜色是last个颜色时方案总数。
既然不可以连续图,所以我们把能连续图的颜色拆分开来使用。
比如说我要用一下子可以涂四个木块的颜色来涂,因为不可以连续,所以我们只让这个颜色图一个木块,那么这个颜色还可以图三个木块,所以我们让可以图三个木块的颜色+1.
如下:
if(d) res=(res+(d-(last==5))*dfs(a,b,c+1,d-1,e,4))%mod;
但是(last==4)表示的是什么意思呢?其实不难理解,如果你要用能涂四个木块的颜色涂,你需要特判一下,上一个木块涂得颜色是不是由5转化为4的,如果不去初这一个,那么相同颜色又挨在一起了。
/*Keep on going Never give up*/ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <math.h> #include <string> #include <list> #include <set> #include <map> #include <queue> #include <stack> #include <algorithm> #include <stdlib.h> #include <vector> const int maxn = 3e5+10; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int mod = 1e9+7; using namespace std; int t[20]; ll dp[16][16][16][16][16][6]; ll dfs(int a,int b,int c,int d,int e,int last){ if(dp[a][b][c][d][e][last]!=-1) return dp[a][b][c][d][e][last]; if(a+b+c+d+e==0) return 1; ll res=0; if(a) res=(res+(a-(last==2))*dfs(a-1,b,c,d,e,1))%mod; if(b) res=(res+(b-(last==3))*dfs(a+1,b-1,c,d,e,2))%mod; if(c) res=(res+(c-(last==4))*dfs(a,b+1,c-1,d,e,3))%mod; if(d) res=(res+(d-(last==5))*dfs(a,b,c+1,d-1,e,4))%mod; if(e) res=(res+e*dfs(a,b,c,d+1,e-1,5)); dp[a][b][c][d][e][last]=res%mod; return dp[a][b][c][d][e][last]; } int main() { int k; cin>>k; memset(dp,-1,sizeof(dp)); for(int i=0;i<k;i++){ int x; cin>>x; t[x]++; } ll ans=dfs(t[1],t[2],t[3],t[4],t[5],0); cout<<ans<<endl; return 0; }