• Codeforces 478D Red-Green Towers:dp


    题目链接:http://codeforces.com/problemset/problem/478/D

    题意:

      给你r个红方块和g个绿方块,让你用这些方块堆一个塔。

      最高层有1个方块,每往下一层块数+1,同时要保证每层中的方块都是同一种颜色。

      如图:

      

      问你在塔的高度最高的前提下,堆出塔的方案数。

    题解:

      假设塔最高能堆d层,则:

        d*(d+1)/2 <= r+g

      解得:

        d = floor((-1+sqrt(1+8*(r+g)))/2)

        并且d最大不超过900。

      表示状态:

        dp[i][j] = numbers

        表示已经堆了最上面的i层,用了j个红方块,此时的方法数。

      

      找出答案:

        ans = ∑ dp[d][max(0,d*(d+1)/2-g) to r]

        因为最终还要保证用了绿方块的个数 <= g,所以枚举i至少要从d*(d+1)/2-g开始。

      如何转移:

        dp[i][j] = dp[i-1][j] + dp[i-1][j-i]

        从上往下数第i层可能全用绿色,或全用红色

      边界条件:

        dp[0][0] = 1

      另外要用滚动数组,否则会MLE。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <math.h>
     5 #define MAX_D 900
     6 #define MAX_R 200005
     7 #define MOD 1000000007
     8 #define EPS 1e-5
     9 
    10 using namespace std;
    11 
    12 int r,g,d;
    13 int dp[2][MAX_R];
    14 
    15 int main()
    16 {
    17     cin>>r>>g;
    18     d=floor((-1.0+sqrt(1.0+8.0*(r+g))+EPS)/2.0);
    19     memset(dp,0,sizeof(dp));
    20     dp[0][0]=1;
    21     for(int i=1;i<=d;i++)
    22     {
    23         for(int j=0;j<=r;j++)
    24         {
    25             dp[i&1][j]=dp[(i-1)&1][j];
    26             if(j-i>=0) dp[i&1][j]+=dp[(i-1)&1][j-i];
    27             dp[i&1][j]%=MOD;
    28         }
    29     }
    30     int ans=0;
    31     for(int i=max(0,d*(d+1)/2-g);i<=r;i++)
    32     {
    33         ans=(ans+dp[d&1][i])%MOD;
    34     }
    35     cout<<ans<<endl;
    36 }
  • 相关阅读:
    精选30道Java笔试题解答
    ASM
    Java Decompiler Plugin For Eclipse IDE
    AMQ5540, AMQ5541 and AMQ5542, application did not supply a user ID and password, 2035 MQRC_NOT_AUTHORIZED
    Shell脚本中的export
    Linux set unset命令
    shell中${}的妙用
    ubuntu alsa2
    ubuntu alsa
    计算机启动boot
  • 原文地址:https://www.cnblogs.com/Leohh/p/8257422.html
Copyright © 2020-2023  润新知