CF431C K-trees

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)



你可能感兴趣的:(CF431C K-trees)