动态规划dp1

核心

把问题分解成相对简单的子问题,来求解复杂问题的方法。核心就是记住已经求解过的子问题的值(与递归的区别)。
解决办法:列出状态转移方程

例一:金币系统

现有的货币系统1、2、5、10等面值。这样18元的价格可以有18x(1元), 9x(2元), 8x(2元)+2x(1元), 3x(5元)+1x(2元)+1x(1元), 等表示方法。
你的任务就是,给定面值的硬币Vi,硬币个数无限多,求出N的价格可以有多少种表示方法。

Input
第一行为一个数字Z,表示一下有Z组测试数据。
每一组测试数据由两行组成,
第一行为两个数V,N。有V (1 <= V <= 25)种硬币,和需要表示的价格N (1 <= N <= 10,000)。
第二行V个数,空格分隔。每一个数Vi表示一种已有的硬币面值。

Output
每组测试数据有一行输出,包括一个数。表示N的价值在由Vi组成的金币系统中有p种表示法。

Sample Input
1
3 10
1 2 5

Sample Output
10

Hint
数据量可能会比较大,保证long long不会溢出。

分析
将v种金币存到a[30]中,求n面值的金币可以有多少种方式组合得到,并用dp[n]存储,现例:a[0]=1,a[1]=2,a[2]=5,n=10
dp[0]=1,面值为0,当然是一种方式 (置dp全为0,再置dp[0]=1)


dp[1]=1=dp[0+a[0]],故dp[1]+=dp[0],面值为1,当然是一种方式
dp[2]=2=dp[1+a[0]]、dp[0+a[1]],故dp[2]+=dp[1],dp[2]+=dp[0],面值为2
dp[3]=dp[2+a[0]]、dp[1+a[1]],故dp[3]+=dp[2],dp[3]+=dp[1],面值为3

转态转移方程:
dp[j+a[i]]+=dp[j]
即面值为10(n=10)的组合方式,分解成·10-a[0]=9,10-a[1]=8,10-a[2]=5
所以dp[10]+=dp[9],dp[10]+=dp[8],dp[10]+=dp[5];//自顶向下理解
(即分解成9的组合方式数+8的组合方式数+5的组合方式数)

9-a[0]=8,9-a[1]=7,9-a[2]=4
dp[9]+=dp[8],dp[9]+=dp[7],dp[9]+=dp[4];

dp[0]=1;
for(int i=0; i<v; i++)
        {
            for(int j=0; j+a[i]<=n; j++)
            {
                dp[j+a[i]]+=dp[j];//自底向上方法
            }
        }

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>//memset方法
#include <vector>
#define LL long long
using namespace std;

int main()
{
    LL a[30],dp[10001];
    int m,v,n,sum;
    scanf("%d",&m);
    while(m--)
    {
        sum=0;
        scanf("%d%d",&v,&n);
        for(int i=0; i<v; i++)
        {
            scanf("%lld",a+i);
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=0; i<v; i++)
        {
            for(int j=0; j+a[i]<=n; j++)
            {
                dp[j+a[i]]+=dp[j];

            }
        }
        printf("%lld\n",dp[n]);

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值