UVA 674 Coin Change【补充分析】

来源:互联网 发布:汇编语言转换成c语言 编辑:程序博客网 时间:2024/06/15 09:34

题目大意:凑钱,求组合方式

解题策略:今天算法课看到rank上此题AC的人最多,但是大多数人感觉没讲明白,在此分享下自己的一点点思考:

                  最近三周做的题目都是DP(动态规划),感觉动态规划要解决三个问题,

                  一,当前状态是什么?

                  二,当前状态的直接前驱状态有哪些?

                  三,当前状态与直接前驱状态的关系?

                  顺着这个思路,我们直接分析核心代码  

void solve(){     dp[0] = 1;     for(int i=0; i<5; i++){        for(int j=1; j<maxn; j++){           if(j >= coin[i])  dp[j] += dp[j-coin[i]];        }     }}

                  1,dp[j]——代表枚举到当前金额coin[i]时,组合j的方案数;dp[0]代表不用任何一个硬币去组合0,所以只有一种方案,dp[0]=1。

                  2,外重循环枚举当前硬币金额,内层枚举金额,循环不可对调,原因是防止重复情况发生,比如组合11, (1,5,5)与(5,5,1)实际是一种方案。

                 

                  刚才提到了解决此题的思路,按部就班解答:

                  一,当前状态是什么?

                         答:枚举到当前硬币金额coin[i]时,组合成j元的方案数——dp[j]。

                 

                  二,当前状态的直接前驱状态有哪些?

                         答:回答这个问题,考虑当前硬币金额coin[i]是否要添加进方案中,

                                1,添加!当前状态dp[j]就是由dp[j-coin[i]]添加当前硬币金额coin[i]或dp[j](枚举上一硬币金额coin[i-1]时,组合j的方案数)添加coin[i]得到;

                                2,不添加!那么当前状态dp[j]是由dp[j](枚举上一硬币金额coin[i-1]时,组合j的方案数)得到,由于未添加当前硬币,故dp[j]值不作修改;

               

                  三,当前状态与直接前驱状态的关系?

                        答:简言之,添不添加当前硬币金额,子状态分别对应dp[j-coin[i]]与dp[j],由于二者不能同时发生,故当判断条件为真时(需要添加当前硬币),

                               dp[j] = dp[j] + dp[j-coin[i]],否则dp[j]不作任何修改。

 

/*   UVA 674 Coin Change   AC by J.Dark   ON 2013/3/12   Time 0.236s*/#include <iostream>#include <cstring>using namespace std;const int maxn = 8000;int dp[maxn];int coin[5]={1, 5, 10, 25, 50};/////////////////////void solve(){     dp[0] = 1;     for(int i=0; i<5; i++){        for(int j=1; j<maxn; j++){           if(j >= coin[i])  dp[j] += dp[j-coin[i]];        }     }}int main(){    int N;    solve();    while(cin >> N)    {       cout << dp[N] << endl;    }    //system("pause");    return 0;}


 

 

原创粉丝点击