题目描述

有n种不同大小的数字Ai,每种各Mi个。判断是否能从这些数字中选出若干个使它们的和恰好为K。

这个问题可以用DP求解,递推关系式的定义会影响最终的复杂度。

第一种定义:

dp[i+1][j],用前i种数字是否能加和成j

为了用前i种数字加和成j,也就需要能用前i-1种数字加和成j,j-Ai,···,j-MiAi中的某一种。由此我们可以定义如下递推关系:

dp[i+1][j]=(0<=k<=Mi且KAi<=j时存在使dp[i][j-kAi]为真的K)

#include<iostream>
#include<stdio.h>
using namespace std;
int n,K;
int a[100],m[100];///a表示数字大小,m表示这个数字的个数
bool dp[100][100];///dp数组 void solve()
{
dp[0][0]=true;
for(int i=0; i<n; i++)
for(int j=0; j<=K; j++)
for(int k=0; k<=m[i]&&k*a[i]<=j; k++)
dp[i+1][j]|=dp[i][j-k*a[i]];
if(dp[n][K])///dp[n][k]存在,即前n个数字能组成和K
printf("Yes\n");
else
printf("No\n");
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
scanf("%d",&m[i]);
scanf("%d",&K);
solve();
return 0;
}

但是这种方法的时间复杂度比较大,因为一般用DP求取bool结果的话会有不少浪费,在这个问题中,我们不仅要求出能否构成目标的和数,同时把得到时Ai这个数还剩下多少个可以使用计算出来,这样就可以减少复杂度。

定义 dp[i+1][j],用前i种数加和得到j时第i种数最多能剩余多少个(不能加和得到i的情况下为-1)。

按照如上所述的递推关系,这样如果前i-1个数加和能得到j的话,第i个数就可以留下Mi个。此外,前i种数加和出j-Ai时第i种数还剩下k(k>0)德华,用这i种数加和j时第i种数就能剩下k-1个。由此我们能得到如下递推:

dp[i+1][j]=Mi; (dp[i][j]>=0)

dp[i+1][j]=-1; (j<Ai或者dp[i+1][j-Ai]<=0)

dp[I+1][j]=dp[I+1][j-Ai]-1; (其他)

这样,只要看最终结果是否满足dp[n][K]>=0就知道答案啦。

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int n,K;
int a[100],m[100];///a表示数字大小,m表示这个数字的个数
bool dp[100];///dp数组 void solve()
{
memset(dp,-1,sizeof(dp));
dp[0]=0;
for(int i=0; i<n; i++)
for(int j=0; j<=K; j++)
{
if(dp[j]>=0)///如果能组成数字j的话,
dp[j]=m[i];
else if(j<a[i]||dp[j-a[i]]<=0)
dp[j]=-1;
else
dp[j]=dp[j-a[i]]-1;
}
if(dp[K]>=0)
printf("Yes\n");
else
printf("No\n");
}
int main()
{
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
for(int i=0; i<n; i++)
scanf("%d",&m[i]);
scanf("%d",&K);
solve();
return 0;
}

多重部分和问题 (dp)的更多相关文章

  1. POJ 1742 Coins ( 经典多重部分和问题 && DP || 多重背包 )

    题意 : 有 n 种面额的硬币,给出各种面额硬币的数量和和面额数,求最多能搭配出几种不超过 m 的金额? 分析 : 这题可用多重背包来解,但这里不讨论这种做法. 如果之前有接触过背包DP的可以自然想到 ...

  2. DP的初级问题——01包、最长公共子序列、完全背包、01包value、多重部分和、最长上升子序列、划分数问题、多重集组合数

    当初学者最开始学习 dp 的时候往往接触的是一大堆的 背包 dp 问题, 那么我们在这里就不妨讨论一下常见的几种背包的 dp 问题: 初级的时候背包 dp 就完全相当于BFS DFS 进行搜索之后的记 ...

  3. 编程算法 - 多重部分和问题 代码(C)

    多重部分和问题 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有n种不同大小的数字a, 每种各m个. 推断能否够从这些数字之中选出若干使它们的 ...

  4. HDU2844(多重部分和)

    Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  5. 多重部分和 poj1742

    Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar. ...

  6. 题解报告:hdu 2844 & poj 1742 Coins(多重部分和问题)

    Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. On ...

  7. 题解报告:hdu 1059 Dividing(多重背包、多重部分和问题)

    Problem Description Marsha and Bill own a collection of marbles. They want to split the collection a ...

  8. POJ1742 coins 动态规划之多重部分和问题

    原题链接:http://poj.org/problem?id=1742 题目大意:tony现在有n种硬币,第i种硬币的面值为A[i],数量为C[i].现在tony要使用这些硬币去买一块价格不超过m的表 ...

  9. POJ_1742_Coins_(动态规划,多重部分和)

    描述 http://poj.org/problem?id=1742 n种不同面额的硬币 ai ,每种各 mi 个,判断可以从这些数字值中选出若干使它们组成的面额恰好为 k 的 k 的个数. 原型: n ...

  10. COJ 0557 4013多重部分和问题

    4013多重部分和问题 难度级别:B: 运行时间限制:2000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 n种大小不同的数字 Ai,每种各Mi个,判断是否可以从 ...

随机推荐

  1. LintCode-69.二叉树的层次遍历

    二叉树的层次遍历 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) 样例 给一棵二叉树 {3,9,20,#,#,15,7} : 返回他的分层遍历结果: [     [3],     [9,2 ...

  2. vim 删除文件全部内容

    很多时候我们需要删除脚本文件全部内容, 重新再写入新的内容,进行其他的操作: 很多时候我们对应用程序的排错需要查看日志文件,然而日志中通常有许多我们以前的应用程序产生的日志,其他的日志过多的时候,有时 ...

  3. Perfmon - Windows 自带系统监控工具

    一. 简述 可以用于监视CPU使用率.内存使用率.硬盘读写速度.网络速度等. Perfmon提供了图表化的系统性能实时监视器.性能日志和警报管理,系统的性能日志可定义为二进制文件.文本文件.SQLSE ...

  4. JXM 监控tomcat 7(含代码

    1.在tomcat的server.xml中加入: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleL ...

  5. Matlab画平滑曲线的两种方法

    自然状态下,用plot画的是折线,而不是平滑曲线. 有两种方法可以画平滑曲线,第一种是拟合的方法,第二种是用spcrv,其实原理应该都一样就是插值.下面是源程序,大家可以根据需要自行选择,更改拟合的参 ...

  6. Android出现:Your project path contains non-ASCII characters.

    导入Project的出现: Error:(1, 0) Your project path contains non-ASCII characters. This will most likely ca ...

  7. RT-thread内核之空闲线程

    空闲线程是系统线程中一个比较特殊的线程,它具有最低的优先级,当系统中无其他线程可运行时,调度器将调度到空闲线程.空闲线程通常是一个死循环,永远不被挂起.RT-Thread实时操作系统为空闲线程提供了钩 ...

  8. 可持久化Treap

    终于写了一次可持久化Treap,做的是可持久化序列的模板题. Treap Treap=Tree+Heap,是一个随机化的数据结构.它的每个节点至少有两个关键字,一个是我们要存储的\(val\),一个是 ...

  9. HDU 4869 Turn the pokers(思维+逆元)

    考试的时候没有做出来... 想到了答案一定是一段连续的区间,一直在纠结BFS判断最后的可行1数. 原来直接模拟一遍就可以算出来最后的端点... 剩下的就是组合数取模了,用逆元就行了... # incl ...

  10. BZOJ 1070 修车(费用流)

    如果能想到费用流,这道题就是显然了. 要求所有人的等待平均时间最小,也就是所有人的总等待时间最小. 每辆车只需要修一次,所以s连每辆车容量为1,费用为0的边. 现在需要把每个人拆成n个点,把车和每个人 ...