货币系统_动态规划_openjudge

题目: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

  1. #include<iostream>
  2. #include<algorithm> 
  3. #include<cstring>
  4. using namespace std;
  5.  
  6. int w[28];
  7. long long dp[10008];
  8.  
  9. int main(){
  10.     int m,n,i,v;
  11.     if(cin>>n>>m){
  12.         memset(dp,0,sizeof(dp));
  13.         dp[0]=1;//这句话代表什么意思? 
  14.         //表示“表示0总价值的货币的方法只有一种” ?
  15.         //在前0中(包括第0种)方式下 
  16.         
  17.         for(i=0;i<n;i++){
  18.             cin>>w[i];
  19.         }
  20.          
  21. //        for(int x=0;x<=m;x++){
  22. //                    cout<<dp[x]<<" ";
  23. //                } cout<<endl;
  24.                 
  25.         for(i=0;i<n;i++){//n种硬币 
  26.             //对于前i 种硬币,有 
  27.             
  28.             //只需要更新不小于钞票值的总钱数部分
  29.             //因为这一部分才有选择此钞票还是不选择此钞票的资格 
  30.             for(v=w[i];v<=m;v++){//m要表示的钱的总值 
  31.                 
  32.                 
  33.                 dp[v]=dp[v]+dp[v-w[i]];
  34. //                for(int x=0;x<=m;x++){
  35. //                    cout<<dp[x]<<" ";
  36. //                } cout<<endl;
  37.             }
  38.         }
  39.         cout<<dp[m]<<endl;
  40.     }
  41. }

猜你喜欢

转载自blog.csdn.net/qq_36160277/article/details/81095141
今日推荐