希望我明天四级稳过…(所以我为什么还在刷题)
这里
题解:题目给的数据范围并不算大,所以我们可以有两个方案,爆搜或者dp,但爆搜不仅不好搜而且肯定会超时,所以我们只好用dp来解决这个问题。
我本来想给每种颜色设一个状态,然后来dp,但5的15次方很明显是超时的,而且也会爆空间。所以我们可以换一种思路,我们看到每种颜色最多只有五个,所以我们可以用五维来表示只能涂n(n>=1&&n<=5)个的木块的油漆各有多少种,再开一维来表示当前选择的是那一维,这样我们就可以用记忆化搜索来解决题目了。
我们需要注意,假设当前我选择了只能涂三个木块的油漆,能涂两块的肯定会多一种,能涂三块的会少一种,但我们下次如果选择能涂两块的是要少一个选择的(因为有一个是从上个三转移过来的,如果再远它颜色会相同)。这样我们就很容易解决这个问题了。
还有不懂得看代码= =
#include<bits/stdc++.h>
#define ll long long
#define pr pair<ll,ll>
#define ios ios::sync_with_stdio(false)
#define CRL(a) memset(a,0,sizeof a)
#define endl "\n"
using namespace std;
const int mod = 1e9 + 7;
int dp[16][16][16][16][16][6];
int t[10];
ll dfs(int a,int b,int c,int d,int e,int last)
{
if(dp[a][b][c][d][e][last])
return dp[a][b][c][d][e][last];
if(a+b+c+d+e==0)
return 1;
ll ans = 0;
if(a)
ans += (a - (last == 2)) * dfs(a - 1, b, c, d, e, 1);
if(b)
ans += (b - (last == 3)) * dfs(a + 1, b - 1, c, d, e, 2);
if(c)
ans += (c - (last == 4)) * dfs(a, b + 1, c - 1, d, e, 3);
if(d)
ans += (d - (last == 5)) * dfs(a, b, c + 1, d - 1, e, 4);
if(e)
ans += (e - 0) * dfs(a, b, c, d + 1, e - 1, 5);
dp[a][b][c][d][e][last] = ans % mod;
return dp[a][b][c][d][e][last];
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n;i++)
{
int a;
cin >> a;
t[a]++;
}
cout << dfs(t[1], t[2], t[3], t[4], t[5], 0);
}