题目:http://ysusoft.openjudge.cn/acm0531/5/
该题属于完全背包的范畴,令dp[i][v]表示用前i种硬币能表示v数量货币的方法数,则对第i种硬币也有选和不选的策略,而总的方案数为二者之和,因此可得状态转移方程:
dp[i][v]=dp[i-1][v]+dp[i][v-w[i]] (1<=i<=n,w[i]<=v<=V)
边界dp[1][v]=1(其余dp初始皆为0),同样,该方程也可以直接去掉i维,但保证v从w[i]开始顺序枚举。
描述转自https://blog.csdn.net/jiangpeng59/article/details/54880741
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- using namespace std;
- int w[28];
- long long dp[10008];
- int main(){
- int m,n,i,v;
- if(cin>>n>>m){
- memset(dp,0,sizeof(dp));
- dp[0]=1;//这句话代表什么意思?
- //表示“表示0总价值的货币的方法只有一种” ?
- //在前0中(包括第0种)方式下
- for(i=0;i<n;i++){
- cin>>w[i];
- }
- // for(int x=0;x<=m;x++){
- // cout<<dp[x]<<" ";
- // } cout<<endl;
- for(i=0;i<n;i++){//n种硬币
- //对于前i 种硬币,有
- //只需要更新不小于钞票值的总钱数部分
- //因为这一部分才有选择此钞票还是不选择此钞票的资格
- for(v=w[i];v<=m;v++){//m要表示的钱的总值
- dp[v]=dp[v]+dp[v-w[i]];
- // for(int x=0;x<=m;x++){
- // cout<<dp[x]<<" ";
- // } cout<<endl;
- }
- }
- cout<<dp[m]<<endl;
- }
- }