其他dp

P2476 [SCOI2008] 着色方案

\(f[a][b][c][d][e][lst]\) 表示当前能涂色 \(1/2/3/4/5\) 个块的个数分别为 \(a/b/c/d/e\),上一层转移过来的状态涂的颜色个数为 \(lst\) 中的一种的方案数。

那么本次转移可以转 \(5\) 种数量的节点,假设我们现在要填写 \(c\) 类情况,那么如果我们上一层节点传下来的 \(lst\)\(4\),那么显然 \(c\) 类中一定会有一个从上一次转下来的相同颜色,所以要乘上 \(c-1\),否则我们乘上 \(c\) 即可。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define getchar() cin.get()
#define int long long
const int N = 16;
const int M = 6;
const int mod = 1e9 + 7;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , t[N] , f[N][N][N][N][N][M];

int dfs ( int a , int b , int c , int d , int e , int lst )
{
    if ( f[a][b][c][d][e][lst] != -1 ) return f[a][b][c][d][e][lst];
    if ( a + b + c + d + e == 0 ) return 1;
    int res = 0;
    if ( a ) res += ( a - ( lst == 2 ) ) * dfs ( a - 1 , b , c , d , e , 1 );
    if ( b ) res += ( b - ( lst == 3 ) ) * dfs ( a + 1 , b - 1 , c , d , e , 2 );
    if ( c ) res += ( c - ( lst == 4 ) ) * dfs ( a , b + 1 , c - 1 , d , e , 3 ); 
    if ( d ) res += ( d - ( lst == 5 ) ) * dfs ( a , b , c + 1 , d - 1 , e , 4 );
    if ( e ) res += ( e - ( lst == 6 ) ) * dfs ( a , b , c , d + 1 , e - 1 , 5 );
    return ( f[a][b][c][d][e][lst] = res ) %= mod;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    n = read();
    for ( int i = 1 ; i <= n ; i ++ ) ++ t[read()];
    memset ( f , -1 , sizeof f );
    cout << dfs ( t[1] , t[2] , t[3] , t[4] , t[5] , 0 ) << endl;
	return 0;
}
posted @ 2023-11-09 20:57  Echo_Long  阅读(4)  评论(0编辑  收藏  举报