题目链接: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 }
原文地址:https://www.cnblogs.com/wsy107316/p/11330732.html
时间: 2024-10-09 23:19:04