您的位置:首页 > 其它

UVA 674 Coin Change【补充分析】

2013-03-12 16:40 441 查看
题目大意:凑钱,求组合方式

解题策略:今天算法课看到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
<< endl;
}
//system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: