• ARC074 E RGB Sequence DP


    ~~~题面~~~

    题解:

      首先,有一个不太直观的状态,f[i][j][k][l]表示DP到i位,三种颜色最后出现的位置分别是j, k, l的方案数。因为知道了三种颜色最后出现的位置,因此也可以得知以当前点为右端点的区间内有几种颜色了,因为左端点不断向左扩张的时候,颜色数不会减少。

      然后考虑优化这个状态,观察到因为每一位都必须有一个颜色,所以这3种颜色当中最后出现的那个所在的位置一定是当前的i。因此我们就可以去掉i,所以复杂度变成了$n^3$,就可以过此题了。

    每次转移之前判断一下是否满足当前右端点的限制,如果不满足就continue,否则枚举颜色转移即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 302
     5 #define ac 500
     6 #define mod 1000000007
     7 #define LL long long
     8 
     9 int n, m;
    10 int Head[AC], date[ac], Next[ac], len[ac], tot;
    11 LL f[AC][AC][AC], ans;
    12 
    13 inline int read()
    14 {
    15     int x = 0;char c = getchar();
    16     while(c > '9' || c < '0') c = getchar();
    17     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    18     return x;
    19 }
    20 
    21 inline void add(int f, int w, int S)
    22 {
    23     date[++tot] = w, Next[tot] = Head[f], Head[f] = tot, len[tot] = S;
    24 }
    25 
    26 inline void pre()
    27 {
    28     int a, b, c;
    29     n = read(), m = read();
    30     for(R i = 1; i <= m; i ++)
    31     {
    32         a = read(), b = read(), c = read();
    33         add(b, a, c);//以右端点为标准
    34     }
    35 }
    36 
    37 inline int Max(int x, int y, int z)
    38 {
    39     if(y > x) x = y;
    40     if(z > x) x = z;
    41     return x;
    42 }
    43 
    44 inline bool check(int x, int y, int z)
    45 {
    46     if(x && y && x == y) return false;
    47     if(x && z && x == z) return false;
    48     if(y && z && y == z) return false;
    49     int k = Max(x, y, z);
    50     for(R i = Head[k]; i; i = Next[i])
    51     {
    52         int now = date[i], v = len[i], tmp = 0;
    53         if(x >= now) ++ tmp;
    54         if(y >= now) ++ tmp;
    55         if(z >= now) ++ tmp;
    56         if(tmp != v) return false;
    57     }
    58     return true;
    59 }
    60 
    61 void work()
    62 {
    63     f[0][0][0] = 1;
    64     for(R i = 0; i <= n; i ++)
    65         for(R j = 0; j <= n; j ++)
    66             for(R l = 0; l <= n; l ++)
    67             {
    68                 int k = Max(i, j, l);
    69                 if(!f[i][j][l]) continue;
    70                 //printf("(%d, %d, %d) = %lld
    ", i, j, l, f[i][j][l]);
    71                 if(!check(i, j, l)) continue;
    72                 LL t = f[i][j][l];
    73                 f[k + 1][j][l] = (f[k + 1][j][l] + t) % mod;
    74                 f[i][k + 1][l] = (f[i][k + 1][l] + t) % mod;
    75                 f[i][j][k + 1] = (f[i][j][k + 1] + t) % mod;
    76                 if(k == n) ans = (ans + f[i][j][l]) % mod;//必须到排到了n
    77             }
    78     printf("%lld
    ", ans);
    79 }
    80 
    81 int main()
    82 {
    83     freopen("in.in", "r", stdin);
    84     pre();
    85     work();
    86     fclose(stdin);
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    搜索
    c++ map与unordered_map区别及使用
    01BFS
    宇智波程序笔记55-Flutter 混合开发】嵌入原生View-iOS
    宇智波程序笔记54-解Bug之路-记一次线上请求偶尔变慢的排查
    宇智波程序笔记53-从红黑树的本质出发,彻底理解红黑树!
    宇智波程序笔记52-最受欢迎的微服务框架概览
    宇智波程序笔记51-JDK 15安装及新特性介绍
    宇智波程序笔记50-解Bug之路-记一次线上请求偶尔变慢的排查
    宇智波程序笔记49-link JDBC Connector:Flink 与数据库集成最佳实践
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9751683.html
Copyright © 2020-2023  润新知