• 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 }
  • 相关阅读:
    oracle学习篇十:序列
    oracle学习篇九:同义词
    oracle相关常识
    oracle之数据同步:Oracle Sql Loader使用说明(大批量快速插入数据库记录)
    oracle学习篇八:约束
    oracle学习篇七:更新操作、事务处理
    oracle学习篇六:子查询
    oracle学习篇五:组函数,分组统计
    oracle学习篇四:多表查询
    oracle学习篇三:SQL查询
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/8476406.html
Copyright © 2020-2023  润新知