Part 1.4 函数,递归及递推

补一补基础题

P1028 [NOIP2001 普及组] 数的计算

题目描述

我们要求找出具有下列性质数的个数(包含输入的正整数 nnn)。

先输入一个正整数 nnn(n≤1000n \le 1000n≤1000),然后对此正整数按照如下方法进行处理:

不作任何处理;

在它的左边加上一个正整数,但该正整数不能超过原数的一半;

加上数后,继续按此规则进行处理,直到不能再加正整数为止。

输入格式

111 个正整数 nnn(n≤1000n \le 1000n≤1000)
输出格式

111 个整数,表示具有该性质数的个数。
输入输出样例
输入

6

输出

6

#include<iostream>
using namespace std;
int main()
{
    
    
    int n,cnt=1,f[1000];
    f[0]=f[1]=1;
    cin>>n;
    for(int i=2;i<=n;i++)
    {
    
    
        if(i%2==0)
        {
    
    
            f[i]=f[i-1]+f[i/2];
        }
        else f[i]=f[i-1];
    }
    cout<<f[n]<<endl;
}

感觉学了这个对动态规划会有更深层次的了解,哎,基础很重要呀,感觉要把基础打牢固了,其实一些比赛就是比谁做的更快,掌握的更牢固呀。

P1464 Function

#include <cstdio>
#define LL long long

LL dp[25][25][25];

LL w(LL a, LL b, LL c)
{
    
    
    if(a <= 0 || b <= 0 || c <= 0) return 1;//两个特判,题意里都有的。
    if(a > 20 || b > 20 || c > 20) return w(20, 20, 20);
    
    if(a <b && b < c)//情况一,每一个没有储存过的“w”值全部储存,如果有就直接调用。
    {
    
    
        if(dp[a][b][c-1] == 0)
        {
    
    
            dp[a][b][c-1] = w(a, b, c-1);
        }
        if(dp[a][b-1][c-1] == 0)
        {
    
    
            dp[a][b-1][c-1] = w(a, b-1 ,c-1);
        }
        if(dp[a][b-1][c] == 0)
        {
    
    
            dp[a][b-1][c] = w(a, b-1, c);
        }
        dp[a][b][c] = dp[a][b][c-1] + dp[a][b-1][c-1] - dp[a][b-1][c];
    }
    
    else//同上
    {
    
    
        if(dp[a-1][b][c] == 0)
        {
    
    
            dp[a-1][b][c] = w(a-1, b, c);
        }
        if(dp[a-1][b-1][c] == 0)
        {
    
    
            dp[a-1][b-1][c] = w(a-1, b-1 ,c);
        }
        if(dp[a-1][b][c-1] == 0)
        {
    
    
            dp[a-1][b][c-1] = w(a-1, b, c-1);
        }
        if(dp[a-1][b-1][c-1] == 0)
        {
    
    
            dp[a-1][b-1][c-1] = w(a-1, b-1, c-1);
        }
        dp[a][b][c] = dp[a-1][b][c] + dp[a-1][b][c-1] + dp[a-1][b-1][c] - dp[a-1][b-1][c-1];
    }
    
    return dp[a][b][c];
}

int main()
{
    
    
    LL a, b, c;
    
    while(scanf("%lld%lld%lld", &a, &b, &c))//无限输入,直到“-1 -1 -1”
    {
    
    
        if(a == -1 && b == -1 && c == -1) return 0;//-1 -1 -1就直接结束,不运算了。
        
        printf("w(%lld, %lld, %lld) = ", a, b, c);
        printf("%lld\n", w(a, b, c));
    }
}

感觉还需要掌握记忆话搜索的精髓

P1025 [NOIP2001 提高组] 数的划分

题目描述

将整数nnn分成kkk份,且每份不能为空,任意两个方案不相同(不考虑顺序)。

例如:n=7n=7n=7,k=3k=3k=3,下面三种分法被认为是相同的。

1,1,51,1,51,1,5;
1,5,11,5,11,5,1;
5,1,15,1,15,1,1.

问有多少种不同的分法。
输入格式

n,kn,kn,k (6<n≤2006<n \le 2006<n≤200,2≤k≤62 \le k \le 62≤k≤6)
输出格式

111个整数,即不同的分法。

#include<iostream>
using namespace std;

int n,k;
inline int dfs(int num,int part,int now)//剩余待分的数 分的机会数 现在要选出的数
{
    
    
    if(part==1)return 1;
    int sum=0;
    for(int i=now;i<=num/part;i++)
    {
    
    
        sum+=dfs(num-i,part-1,i);
    }
    return sum;
}

int main()
{
    
    
    cin>>n>>k;
    cout<<dfs(n,k,1)<<endl;
}

感觉又是一道很好的dfs题 但是这个的动态规划感觉有点难想 转移方程不大会写呢

猜你喜欢

转载自blog.csdn.net/m0_51344983/article/details/113079874
1.4
今日推荐