蓝桥杯 算法训练 K好数(DP C++)

时间:2022-09-09 23:09:50

蓝桥杯 算法训练 K好数(DP C++)

【思路分析】
题目的意思是,求2位四进制数(只有0 1 2 3这四个数字)中,K好数的个数是多少。

状态:定义DP数组,DP[i][j]表示共i位数且结尾数字是j的K好数的个数。
当i=1时,也就是数字位数是1时,所有的数字都是K好数,因为没有数字相邻的情况。但是因为开头数字是j,所以要注意第一个数字不能是0,所以赋值时从1开始,最大为k-1。

状态转移方程:dp[i][j]=(dp[i][j]+dp[i-1][q])。
其实就是从第一个数字开始,逐个找出后面的数字不能与前一个数字相邻的情况有多少种,直到i=l为止。
最后,将长度为l的以0,1,2……k-1结尾的K好数的个数加起来。


【题解代码】

#include<stdio.h>
#include<string.h>

int dp[105][105];
int main(){
int k,l;
while(scanf("%d%d",&k,&l)!=EOF){ // 循环语句内等价于~scanf()
memset(dp,0,sizeof(dp)); // 可有可无
/*void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节用ch替换并返回s。
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法*/


for(int i=1;i<k;i++)//当数字位数为1时,从1开始,个数都是1,K好数就是i
dp[1][i]=1;
for(int i=2; i<=l; i++){ // i控制位数
for(int j=0;j<k;j++){ // j是前一位,数字的取值范围是0~k-1
for(int q=0;q<k;q++){ // q是后一位,数字的取值范围是0~k-1
if(j-q==1 || j-q==-1) continue;
dp[i][j]=(dp[i][j]+dp[i-1][q])%1000000007;
}
}
}
long long ans=0;
for(int i=0;i<k;i++)
ans+=dp[l][i]; // 位数为l的方案数加和
printf("%d\n",ans%1000000007);
}
return 0;
}