zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    poj 1328 Radar Installation (贪心)
    hdu 2037 今年暑假不AC (贪心)
    poj 2965 The Pilots Brothers' refrigerator (dfs)
    poj 1753 Flip Game (dfs)
    hdu 2838 Cow Sorting (树状数组)
    hdu 1058 Humble Numbers (DP)
    hdu 1069 Monkey and Banana (DP)
    hdu 1087 Super Jumping! Jumping! Jumping! (DP)
    必须知道的.NET FrameWork
    使用记事本+CSC编译程序
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9751683.html
Copyright © 2011-2022 走看看