着色方案(动态规划+记忆化搜索)

题目链接https://www.lydsy.com/JudgeOnline/problem.php?id=1079

AC代码:

 1 /*
 2     直接状态压缩是显然是不可行的,我们考虑如果没有相邻颜色不相同的限制的话,
 3     如果两种油漆能染的木块数目相同,我们就可以认为两种油漆无差别。
 4     设dp[a1][a2][a3][a4][a5]为能染1个木块的油漆有a1种……的方案数。
 5     但是有相邻颜色的限制,如果上一次用了颜色数为k的油漆,
 6     那么这一次有一种颜色数为k-1的油漆就不能用了,转移的时候注意一下。
 7 */
 8 # include <iostream>
 9 # include <stdio.h>
10 # include <string.h>
11 # include <algorithm>
12 # include <bitset>
13 # include <ctime>
14 # include <climits>
15 # include <set>
16 # include <map>
17 # include <cctype>
18 # include <cmath>
19 # include <deque>
20 # include <queue>
21 # include <stack>
22 # include <vector>
23 # include <functional>
24 using namespace std;
25 
26 typedef long long LL;
27 const int maxn=16;
28 const LL mod=1e9+7;
29 int n, x[16];
30 LL f[16][16][16][16][16][6];///f数组表示当前有能涂1次的油漆a个,能涂2次的b个....前一个涂的是还能涂k次的油漆
31 bool dp[16][16][16][16][16][6];
32 
33 LL Dp(int a, int b, int c, int d, int e, int k)
34 {
35     LL t=0;
36     if( dp[a][b][c][d][e][k] )
37         return f[a][b][c][d][e][k];
38     if( a+b+c+d+e==0 )
39         return 1;
40     if( a )
41         t = t+(a-(k==2))*Dp(a-1, b, c, d, e, 1);///一种可以染1个方块的颜色,变成了可以染0个方块(所以a-1),如果上一次用了颜色数为2的油漆, 那么这一次有一种颜色数为1的油漆就不能用了
42     if( b )
43         t = t+(b-(k==3))*Dp(a+1, b-1, c, d, e, 2);///一种可以染2个方块的颜色,变成了可以染1个方块(所以b-1, a+1),如果上一次用了颜色数为3的油漆, 那么这一次有一种颜色数为2的油漆就不能用了
44     if( c )
45         t = t+(c-(k==4))*Dp(a, b+1, c-1, d, e, 3);///一种可以染3个方块的颜色,变成了可以染2个方块(所以c-1, b+1),如果上一次用了颜色数为4的油漆, 那么这一次有一种颜色数为3的油漆就不能用了
46     if( d )
47         t = t+(d-(k==5))*Dp(a, b, c+1, d-1, e, 4);///一种可以染4个方块的颜色,变成了可以染3个方块(所以d-1, c+1),如果上一次用了颜色数为5的油漆, 那么这一次有一种颜色数为4的油漆就不能用了
48     if( e )
49         t = t+e*Dp(a, b, c, d+1, e-1, 5);///一种可以染5个方块的颜色,变成了可以染4个方块(所以e-1, d+1),如果这一次用可以染5个方块的颜色,因为题目有条件1 <= ci <= 5,所以说明他之前一定没用过
50     dp[a][b][c][d][e][k] = 1;
51     return f[a][b][c][d][e][k] = (t%mod);
52 }
53 
54 int main()
55 {
56     scanf("%d", &n);
57     for(int i=1; i<=n; i++)
58     {
59         int y;
60         scanf("%d", &y);
61         x[y]++;
62     }
63     printf("%lld\n", Dp(x[1], x[2], x[3], x[4], x[5], 0));
64     return 0;
65 }
View Code

猜你喜欢

转载自www.cnblogs.com/wsy107316/p/11330732.html