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

  • 相关阅读:
    Candy leetcode java
    Trapping Rain Water leetcode java
    Best Time to Buy and Sell Stock III leetcode java
    Best Time to Buy and Sell Stock II leetcode java
    Best Time to Buy and Sell Stock leetcode java
    Maximum Subarray leetcode java
    Word Break II leetcode java
    Word Break leetcode java
    Anagrams leetcode java
    Clone Graph leetcode java(DFS and BFS 基础)
  • 原文地址:https://www.cnblogs.com/AC-Phoenix/p/4296669.html
Copyright © 2011-2022 走看看