• 鸣人的影分身


    题目

    题目链接

    题目描述

    在火影忍者的世界里,令敌人捉摸不透是非常关键的。

    我们的主角漩涡鸣人所拥有的一个招数——多重影分身之术——就是一个很好的例子。

    影分身是由鸣人身体的查克拉能量制造的,使用的查克拉越多,制造出的影分身越强。

    针对不同的作战情况,鸣人可以选择制造出各种强度的影分身,有的用来佯攻,有的用来发起致命一击。

    那么问题来了,假设鸣人的查克拉能量为(M),他影分身的个数最多为(N),那么制造影分身时有多少种不同的分配方法?

    注意:

    影分身可以分配0点能量。
    分配方案不考虑顺序,例如(M)=7,(N)=3,那么 (2,2,3) 和 (2,3,2) 被视为同一种方案。

    输入格式

    第一行是测试数据的数目(t)

    以下每行均包含二个整数(M)(N),以空格分开。

    输出格式

    对输入的每组数据(M)(N),用一行输出分配的方法数。

    数据范围

    (0le tle 20),
    (1le M, Nle 10)

    输入样例:

    1
    7 3

    输出样例:

    8

    分析

    用到的知识

    1.dfs
    2.Dp状态计算中很奇怪的分法。

    代码

    dfs

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    const int N = 15;
    
    int f[N];
    
    int n, m;
    LL ans;
    
    // u代表dfs到了哪一位,s代表已经用了多少查克拉,st就是start的缩写代表着从多少开始,因为本题总不考虑顺序,所以我们自己规定一个不减小的顺序
    void dfs(int u, int s, int st)
    {
        if (s > n) return; // 剪枝,如果大于查克拉总量 return
        if (u == m + 1) // 找完所有位
        {    
            if (s == n) ans++;
            return;
        }
        for (int i = st; i <= n; i++)
        {
            f[u] = i;
            dfs(u + 1, s + i, i);
        }
    }
    
    int main()
    {
        int t;
        cin >> t;
        
        while (t--)
        {
            cin >> n >> m;
            dfs(1, 0, 0);
            cout << ans << endl;
            ans = 0;
        }
        
        return 0;
    }
    

    Dp

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 15;
    
    int m, n;
    int f[N][N];
    
    int main()
    {
        int t;
        cin >> t;
        
        while (t--)
        {
            cin >> m >> n;
            // 这里的初始化很烦,因为本题中可以分配0,所以总量为0时分成任意非负份的方案数均为1
            for (int i = 0; i <= n; i++) f[0][i] = 1; 
    
            for (int i = 1; i <= m; i++)
                for (int j = 1; j <= n; j++)
                {
                    f[i][j] = f[i][j - 1];
                    if (i >= j) f[i][j] += f[i - j][j];
                }
            cout << f[m][n] << endl;
            memset(f, 0, sizeof(f));
        }
        
        return 0;
    }
    
  • 相关阅读:
    第二章 逻辑代数及其简化
    小知识:三极管ie==ic+ib
    第二章.2 真值表→表达式的转换
    C# 静态变量及静态函数
    第四章(1):变量静态变量和实例变量
    转义大括号
    能被15整除的最大整数
    动态规划矩阵连乘问题
    [转]三极管的集电结反向偏置电压
    anddroid App, Framework, Sdk编译
  • 原文地址:https://www.cnblogs.com/optimjie/p/12321203.html
Copyright © 2020-2023  润新知