zoukankan      html  css  js  c++  java
  • CodeForces 268D a nice dp

    //先贴一发错误的代码,dp[层数][方向]

    //因为是对不完整的方案计数了...

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "algorithm"
     5 using namespace std;
     6 const __int64 mod = 1e9 + 9;
     7 __int64 dp[1010][5];
     8 int n, h;
     9 
    10 int main()
    11 {
    12     int i, j, k;
    13     scanf("%d%d", &n, &h);
    14     for(j = 1; j <= 4; ++j)
    15         dp[1][j] = 1;
    16     for(i = 2; i <= n; ++i) {
    17         for(j = 1; j <= 4; ++j) {
    18             for(k = max(1, i - h); k <= i - 1; ++k) {
    19                 dp[i][j] += dp[k][j];
    20                 dp[i][j] %= mod;
    21             }
    22             //printf("dp[%d][%d] == %I64d
    ", i, j, dp[i][j]);
    23         }
    24     }
    25     __int64 res = 0;
    26     for(i = n - h + 1; i <= n; ++i)
    27         for(j = 1; j <= 4; ++j)
    28             res += dp[i][j], res %= mod;
    29     printf("%I64d
    ", res);
    30 }

    //将方案补充完整又不至于方案之间的重复,直观的方法构造到 [n - h + 1, n] 中的任意一层的上层都是不可达的,但是 dp[i][j] 是过去所有状态的最好解释,用一种优美的方式分析出 dp[i][j] 且又达到构造不可达层的目的......还是换个姿势吧

    //看了一下网上的题解,看到了别人构造的状态简直可怕...被吓到的我决定自己模仿构造一个压压惊,结果写出了 __int64 dp[1010][31][31][31][31]; 这个傻逼的超大状态...没办法去压缩一下空间吧,结果在第五组数据上 T 了... 跟正解相比,时间和空间消耗都增加了...

    //Time limit exceeded on test 5

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "algorithm"
     5 using namespace std;
     6 const int mod = 1e9 + 9;
     7 int dp[2][31][31][31][31];
     8 int n, h;
     9 void add(int &ans, int val)
    10 {
    11     if((ans += val) > mod)
    12         ans -= mod;
    13 }
    14 
    15 int main()
    16 {
    17     int i, a, b, c, d;
    18     int val;
    19     bool now = 0;
    20     scanf("%d%d", &n, &h);
    21     dp[0][0][0][0][0] = 1;
    22     for(i = 0; i <= n - 1; ++i) {
    23         now ^= 1;
    24         memset(dp[now], 0, sizeof(dp[now]));
    25         for(a = 0; a <= h; ++a) {
    26             for(b = 0; b <= h; ++b) {
    27                 for(c = 0; c <= h; ++c) {
    28                     for(d = 0; d <= h; ++d) {
    29                         if(val = dp[now^1][a][b][c][d]) {
    30                             add(dp[now][a < h? 0: h][b < h? b + 1: h][c < h? c + 1: h][d < h? d + 1: h], val);
    31                             add(dp[now][a < h? a + 1: h][b < h? 0: h][c < h? c + 1: h][d < h? d + 1: h], val);
    32                             add(dp[now][a < h? a + 1: h][b < h? b + 1: h][c < h? 0: h][d < h? d + 1: h], val);
    33                             add(dp[now][a < h? a + 1: h][b < h? b + 1: h][c < h? c + 1: h][d < h? 0: h], val);
    34                         }
    35                     }
    36                 }
    37             }
    38         }
    39     }
    40     int res = 0;
    41     for(a = 0; a <= h; ++a)
    42         for(b = 0; b <= h; ++b)
    43             for(c = 0; c <= h; ++c)
    44                 for(d = 0; d <= h; ++d)
    45                     if((val = dp[now][a][b][c][d]) && (a < h || b < h || c < h || d < h))
    46                         add(res, dp[now][a][b][c][d]);
    47     printf("%d
    ", res);
    48 }

    //按照正解的思路写了一下

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "algorithm"
     5 using namespace std;
     6 const int mod = 1e9 + 9;
     7 int dp[1010][2][31][31][31];
     8 int n, h;
     9 void add(int &ans, int val)
    10 {
    11     if((ans += val) > mod)
    12         ans -= mod;
    13 }
    14 
    15 int main()
    16 {
    17     int i, a, b, c, d;
    18     int val;
    19     scanf("%d%d", &n, &h);
    20     dp[0][0][0][0][0] = 1;
    21     for(i = 0; i <= n - 1; ++i) {
    22         for(a = 0; a <= 1; ++a) {
    23             for(b = 0; b <= h; ++b) {
    24                 for(c = 0; c <= h; ++c) {
    25                     for(d = 0; d <= h; ++d) {
    26                         if(val = dp[i][a][b][c][d]) {
    27                             add(dp[i + 1][a < 1? 0: 1][b < h? b + 1: h][c < h? c + 1: h][d < h? d + 1: h], val);
    28                             add(dp[i + 1][b < h? 0: 1][c < h? c + 1: h][d < h? d + 1: h][a < 1? a + 1: h], val);
    29                             add(dp[i + 1][c < h? 0: 1][d < h? d + 1: h][a < 1? a + 1: h][b < h? b + 1: h], val);
    30                             add(dp[i + 1][d < h? 0: 1][a < 1? a + 1: h][b < h? b + 1: h][c < h? c + 1: h], val);
    31                         }
    32                     }
    33                 }
    34             }
    35         }
    36     }
    37     int res = 0;
    38     for(a = 0; a <= 1; ++a)
    39         for(b = 0; b <= h; ++b)
    40             for(c = 0; c <= h; ++c)
    41                 for(d = 0; d <= h; ++d)
    42                     if((val = dp[n][a][b][c][d]) && (a < 1 || b < h || c < h || d < h))
    43                         add(res, dp[n][a][b][c][d]);
    44     printf("%d
    ", res);
    45 }

    //正解大概的意思是,我们每在一层选取一个方向建造一个 bar 之后,可以影响到包括另外三个方向在内(一共四个方向)的距离状态,然后出题人用智商将一个方向的距离状态压缩成了 [2] ,分别表示 bar 的可达与不可达(具体做法是选取这个方向为建造 bar 的方向,hint:因为我们每次都会在这个方向上建造 bar,所以 如果在刚刚建造的方向建造 新bar 或者 另外三个方向在前一个状态时距离状态还没到达 h - 1,那么在 4 个方向上建造的 新bar 都是可达的),四个方向依次旋转一遍表示在四个方向上建造 bar

  • 相关阅读:
    网络问题排查
    SpringBoot 自定义注解清除缓存
    MYSQL外键的使用以及优缺点
    Java List
    黑客帝国代码雨
    前端接收字节数据流,显示图片
    何为熔断降级
    spring的线程
    window.open 与 iframe
    js 全部替换
  • 原文地址:https://www.cnblogs.com/AC-Phoenix/p/4296669.html
Copyright © 2011-2022 走看看