题意:
有
n
个
木
块
有n个木块
有n个木块
k
种
油
漆
,
每
种
c
i
个
k种油漆,每种c_i个
k种油漆,每种ci个
c
1
+
c
2
+
…
…
+
c
k
=
n
c_1+c_2+……+c_k=n
c1+c2+……+ck=n
相
邻
两
个
木
块
不
能
涂
相
同
颜
色
相邻两个木块不能涂相同颜色
相邻两个木块不能涂相同颜色
求
方
案
数
求方案数
求方案数
题解:
k
<
=
15
,
c
i
<
=
5
k<=15,c_i<=5
k<=15,ci<=5
数
据
很
小
,
所
以
可
以
直
接
考
虑
暴
力
算
法
数据很小,所以可以直接考虑暴力算法
数据很小,所以可以直接考虑暴力算法
但
是
枚
举
每
种
颜
色
的
话
,
颜
色
种
类
数
是
15
,
仍
然
会
超
时
但是枚举每种颜色的话,颜色种类数是15,仍然会超时
但是枚举每种颜色的话,颜色种类数是15,仍然会超时
但
是
c
i
很
小
,
可
以
从
这
里
进
行
操
作
但是c_i很小,可以从这里进行操作
但是ci很小,可以从这里进行操作
可
以
每
次
选
择
固
定
的
c
i
进
行
使
用
可以每次选择固定的c_i进行使用
可以每次选择固定的ci进行使用
记
忆
化
搜
索
5
种
个
数
的
颜
色
记忆化搜索5种个数的颜色
记忆化搜索5种个数的颜色
d
p
[
a
]
[
b
]
[
c
]
[
d
]
[
e
]
[
l
a
]
dp[a][b][c][d][e][la]
dp[a][b][c][d][e][la]
表
示
现
在
有
a
种
1
个
,
b
种
2
个
,
e
种
5
个
颜
色
的
油
漆
,
并
且
上
一
个
用
了
l
a
个
颜
色
的
表示现在有a种1个,b种2个,e种5个颜色的油漆,并且上一个用了la个颜色的
表示现在有a种1个,b种2个,e种5个颜色的油漆,并且上一个用了la个颜色的
对
于
每
次
使
用
,
会
使
得
当
前
个
数
颜
色
的
油
漆
减
少
对于每次使用,会使得当前个数颜色的油漆减少
对于每次使用,会使得当前个数颜色的油漆减少
使
得
当
前
个
数
减
一
的
颜
色
油
漆
增
加
使得当前个数减一的颜色油漆增加
使得当前个数减一的颜色油漆增加
所
以
如
果
上
次
使
用
的
油
漆
颜
色
是
这
次
使
用
颜
色
个
数
加
一
所以如果上次使用的油漆颜色是这次使用颜色个数加一
所以如果上次使用的油漆颜色是这次使用颜色个数加一
就
需
要
减
去
一
个
,
就
是
上
次
使
用
的
颜
色
,
使
其
不
会
相
邻
就需要减去一个,就是上次使用的颜色,使其不会相邻
就需要减去一个,就是上次使用的颜色,使其不会相邻
然
后
直
接
搜
索
并
且
维
护
值
即
可
然后直接搜索并且维护值即可
然后直接搜索并且维护值即可
AC代码
/*
Author : zzugzx
Lang : C++
Blog : blog.youkuaiyun.com/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
const int MOD = 998244353;
const double eps = 1e-10;
const double pi = acos(-1.0);
const int maxn = 1e6 + 10;
//const int N = 1e3 + 10;
const ll inf = 0x3f3f3f3f;
const int dir[][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
ll dp[16][16][16][16][16][6], t[6];
ll dfs(int a, int b, int c, int d, int e, int la) {
if (dp[a][b][c][d][e][la] != -1)
return dp[a][b][c][d][e][la];
if (a + b + c + d + e == 0)
return 1;
ll ans = 0;
if (a) ans = (ans + (a - (la == 2)) * dfs(a - 1, b, c, d, e, 1)) % mod;
if (b) ans = (ans + (b - (la == 3)) * dfs(a + 1, b - 1, c, d, e, 2)) % mod;
if (c) ans = (ans + (c - (la == 4)) * dfs(a, b + 1, c - 1, d, e, 3)) % mod;
if (d) ans = (ans + (d - (la == 5)) * dfs(a, b, c + 1, d - 1, e, 4)) % mod;
if (e) ans = (ans + e * dfs(a, b, c, d + 1, e - 1, 5)) % mod;
return dp[a][b][c][d][e][la] = ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int k;
cin >> k;
for (int i = 1; i <= k; i++){
int x;
cin >> x;
t[x]++;
}
memset(dp, -1, sizeof dp);
cout << dfs(t[1], t[2], t[3], t[4], t[5], 0);
return 0;
}