object cf431C { val MOD:Int = 1000000007 def main(args : Array[String]) : Unit = { val sc = new Scanner(System.in) val n,k,d = sc.nextInt val dp = Array.ofDim[Int](105, 2) dp(0)(0) = 1 for(i <- 0 until n; j<- 0 to 1;r<- 1 to k){ if(i+r<=n){ val flag = if(j==1 || r>=d) 1 else 0 dp(i+r)(flag) = (dp(i)(j)+dp(i+r)(flag))% MOD } } println(dp(n)(1)) } }
第一步:设dp[i][j] 表示长度路径权重和为j,并且路径中最大的节点权重为j的条数。
那么从根节点出发的路径可以初始为1,即dp[0][0] = 1
第二步:动态转移方程dp[i][j>r?j:r] = dp[i-r][r]+dp[i][>r?j:r] ( r<=i<=n,1<=r<=k)
第三步:求和。题意中的不少于路径中最大权重节点不小于d,所以answer = sum(dp[n][n<=t<=k])
简化转移方程:
事实上dp的状态只有两种即路过的结点权重不小于d,或者小于d。把这个算作两种状态。
转移方程即可转化为dp[i][ r>d || j ?]+=dp[i-r][j] (r<=i<=n,j@(0,1),1<=r<=k)