题型:动态规划
题意:
k-Tree,每个节点有k个儿子,边权分别是1、2、……、K。
现求出从根节点出发,有多少条路径,使得总权值恰好为N,并且每条路径上至少有一条权值不少于d的边。
分析:
对于动态规划,要首先考虑要求的是神马。对于本题,要求的是权值和为N,且至少有一条权值不少于d的边的路径的个数。
为了便于思考,先不考虑保证要有不少于d的边,那么可以定义dp[n]表示最后的答案,则有方程:
dp[n] = dp[n-1]+dp[n-2]+......+dp[n-k]
重新考虑题目的要求,则定义dp[i][x]表示当到达i状态时的总数,x为0或1,0表示之前没有使用过>=d的边,1表示之前有使用过>d的边。
则有状态转移方程:
dp[i+j][0] += dp[i][0] , (j < d)
dp[i+j][1] += dp[i][0] , (j>=d)
dp[i+j][1] += dp[i][1]
初始化dp[0][0] = 1;
最终答案存在dp[n][1】中。
代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#define LL __int64
#define MOD 1000000007
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
LL dp[123][2];
int main(){
int n,k,d;
while(~scanf("%d%d%d",&n,&k,&d)){
mt(dp,0);
dp[0][0] = 1;
for(int i=0;i<n;i++){
for(int j=1;j<=k;j++){
if(i+j>n) continue;
if(j<d) dp[i+j][0] += dp[i][0];
else dp[i+j][1] += dp[i][0];
dp[i+j][1] += dp[i][1];
dp[i+j][0] %= MOD;
dp[i+j][1] %= MOD;
}
}
printf("%I64d\n",dp[n][1]);
}
return 0;
}