题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1101
题意:中文题诶~
思路:dp
我们用dp[i][j]存储前i中币值总价值为j的方法数,那么动态转移方程式为:
if(j>=gg[i]) //放的下第i中币值
dp[i][j]=dp[i-1][j]+dp[i][j-gg[i]]
else //放不下第i中币值
dp[i][j]=dp[i-1][j]
代码:
1 #include <iostream> 2 #define ll long long 3 #define MAXN 100010 4 using namespace std; 5 6 const int mod=1e9+7; 7 ll gg[]={0, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000}; 8 ll dp[15][MAXN]; //***dp[i][j]存储前i中币值总价值为j的方法数 9 10 int main(void){ 11 int n; 12 cin >> n; 13 dp[0][0]=1; 14 for(int i=1; i<=13; i++){ 15 for(int j=0; j<=n; j++){ 16 if(j>=gg[i]){ //***放的下 17 dp[i][j]=(dp[i-1][j]+dp[i][j-gg[i]])%mod; 18 }else{ //***放不下 19 dp[i][j]=dp[i-1][j]; 20 } 21 } 22 } 23 cout << dp[13][n] << endl; 24 return 0; 25 }
因为dp[i][]的情况都是由dp[i-1]得到的,所以我们可以直接用一维数组就好了~
代码:
1 #include <iostream> 2 #define ll long long 3 #define MAXN 100010 4 using namespace std; 5 6 const int mod=1e9+7; 7 ll gg[]={1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000}; 8 ll dp[MAXN]; 9 10 int main(void){ 11 int n; 12 cin >> n; 13 dp[0]=1; 14 for(int i=0; i<13; i++){ //***选用前i+1种币值 15 for(int j=gg[i]; j<=n; j++){ //***总价值为j的方法数 16 dp[j]=(dp[j]+dp[j-gg[i]])%mod; 17 } 18 } 19 cout << dp[n] << endl; 20 return 0; 21 }
时间: 2024-10-17 14:03:23