JN 刷墙 过程DP

题目

3 刷墙(wall.c/cpp/pas)
3.1 题目描述
Will 被指派去刷墙. 他⼀共需要刷N ⾯墙, 每⾯墙要求刷⼀种颜⾊. 他⼀共有N 桶油漆, 这些油漆⼀共有3
种颜⾊, 每种颜⾊的油漆分别有C0, C1, C2 桶. 刷⼀⾯墙需要⽤⼀桶油漆, 这N 桶油漆恰好可以刷完这N ⾯墙
(C0 + C1 + C2 = N).
但刷墙也不是随便可以刷的. Will 要求, 相邻的墙⾯的颜⾊⼀定要满⾜他的要求. 他有时会希望某两种颜⾊可
以不连续出现. 他想知道, 在满⾜他的要求下, ⼀共由多少种刷墙的⽅式呢?
3.2 输入格式(wall.in)
第⼀⾏四个整数C0;C1;C2;K, 分别代表每种颜⾊的油漆桶数, 以及Will 的要求数.
接下来K ⾏每⾏两个整数Xi; Yi, 代表颜⾊为Xi 和Yi 的油漆不能相邻(例如, 0 和1 不能相邻, 则出现相邻墙
⾯是0,1 或者是1,0 都是不合法的).
3.3 输出格式(wall.out)
⼀⾏⼀个整数, 总的刷墙⽅式对109 + 7 = 1000000007 取模后的值.
3.4 样例输入
1 2 2 3
0 0
1 1
2 2
3.5 样例输出
12
3.6 样例解释
共有1 + 2 + 2 = 5 ⾯墙, 颜⾊0 有⼀桶油漆, 颜⾊1 有两桶油漆, 颜⾊2 有两桶油漆; Will 要求相同颜⾊的不
能相邻.
3.7 数据规模及约束
对于30% 的数据, 满⾜Ci  5;
对于50% 的数据, 满⾜Ci  30;
对于100% 的数据, 满⾜0  Ci  100; 0  K  6; 0  Xi; Yi  2.
3.8 时间空间限制
1s, 256M
3

分析

写出一个30分的爆搜不是什么难事,

- dfs(x, y, z, p) 现在剩余C0x 桶, C1y 桶, C2z 桶, 最后刷的颜色是p
- 然后枚举下一面墙刷什么颜色
- 从dfs(C0; C1; C2) 开始刷, 一直刷到dfs(0,0,0) 结束

这样我们就很容易想到接下来100分算法的状态怎么写了,

- 设F[x][y][z][p] 是现在剩余C0x 桶, C1y 桶, C2z 桶, 最后刷的颜色是p, 一共有多少种方案

- 然后进行一波顺推,推到答案F[0][0][0][p],答案是F[0][0][0][0]...F[0][0][0][2]的最大值

程序

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAXC = 100 + 1, MOD = 1000000007;
 4 int ban1, ban2, f[MAXC][MAXC][MAXC][3], c1, c2, c3, ans, m;
 5 bool ban[3][3];
 6 int main()
 7 {
 8     freopen("wall.in","r",stdin);
 9     freopen("wall.out","w",stdout);
10     cin >> c1 >> c2 >> c3 >> m;
11     for (int i = 1; i <= m; i++)
12         cin >> ban1 >> ban2, ban[ban1][ban2] = ban[ban2][ban1] = true;
13     if(c1)
14         f[1][0][0][0] = 1;
15     if(c2)
16         f[0][1][0][1] = 1;
17     if(c3)
18         f[0][0][1][2] = 1;
19     for (int i = 0; i <= c1; i++)
20         for (int j = 0; j <= c2; j++)
21             for (int k = 0; k <= c3; k++)
22             {
23                 if (i)
24                 {
25                     int g = f[i][j][k][0];
26                     if(i<c1 && !ban[0][0])
27                         (f[i+1][j][k][0] += g) %= MOD;
28                     if(j<c2 && !ban[0][1])
29                         (f[i][j+1][k][1] += g) %= MOD;
30                     if(k<c3 && !ban[0][2])
31                         (f[i][j][k+1][2] += g) %= MOD;
32                 }
33                 if (j)
34                 {
35                     int g = f[i][j][k][1];
36                     if(i<c1 && !ban[1][0])
37                         (f[i+1][j][k][0] += g) %= MOD;
38                     if(j<c2 && !ban[1][1])
39                         (f[i][j+1][k][1] += g) %= MOD;
40                     if(k<c3 && !ban[1][2])
41                         (f[i][j][k+1][2] += g) %= MOD;
42                 }
43                 if (k)
44                 {
45                     int g = f[i][j][k][2];
46                     if(i<c1 && !ban[2][0])
47                         (f[i+1][j][k][0] += g) %= MOD;
48                     if(j<c2 && !ban[2][1])
49                         (f[i][j+1][k][1] += g) %= MOD;
50                     if(k<c3 && !ban[2][2])
51                         (f[i][j][k+1][2] += g) %= MOD;
52                 }
53             }
54     int ans = ((f[c1][c2][c3][0] + f[c1][c2][c3][1]) % MOD + f[c1][c2][c3][2]) % MOD;
55     cout << ans << endl;
56     return 0;
57 }
原文地址:https://www.cnblogs.com/OIerPrime/p/8476406.html