第十一届蓝桥杯 校内模拟赛 第9题(记忆化搜索解题)

问题描述
  小明想知道,满足以下条件的正整数序列的数量:
  1. 第一项为 n;
  2. 第二项不超过 n;
  3. 从第三项开始,每一项小于前两项的差的绝对值。
  请计算,对于给定的 n,有多少种满足条件的序列。
输入格式
  输入一行包含一个整数 n。
输出格式
  输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
样例输入
4
样例输出
7
样例说明
  以下是满足条件的序列:
  4 1
  4 1 1
  4 1 2
  4 2
  4 2 1
  4 3
  4 4
评测用例规模与约定
  对于 20% 的评测用例,1 <= n <= 5;
  对于 50% 的评测用例,1 <= n <= 10;
  对于 80% 的评测用例,1 <= n <= 100;
  对于所有评测用例,1 <= n <= 1000。

解题思路
记忆化搜索:因为本题难以找出状态转移方程,所以无法用传统的动态规划的思路去解。记忆化搜索其实就是用搜索的方式,解决了动态规划只会按照循环遍历而对状态转移方程不确定的情况无法求解的缺点。记忆化搜索结合了动态规划记录之前状态的特点,采用递归法进行求解。记忆化搜索可以排除一些无效的状态且避免重复的运算。

本题思路:用dp[i][j],表示前一个数为i,后一个数为j时,产生的满足题目中条件3的序列。而且本题中dp[i][j]与之前状态的关系为dp[x][y]=dp[x][y]+∑DFS(y,i),1<=i

源代码

#include 
#include 

int dp[1010][1010];

int DFS(int x,int y)
{
    if(dp[x][y]>1)return dp[x][y];
    for(int i=1;i<abs(x-y);i++)
    {
        dp[x][y]+=DFS(y,i);
    }
    dp[x][y]%=10000;
    return dp[x][y];
}
int main()
{
    int n;
    scanf("%d",&n);
    int ans=0;
    for(int i=0;i<=n;i++){
        for(int j=0;j<=n;j++){
            dp[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        ans=(ans+DFS(n,i))%10000;
    }
    printf("%d\n",ans);
}

如有错误,还请及时联系我进行修改!!!

你可能感兴趣的:(蓝桥杯省赛备战)