货币系统
这道题说坑不坑......说不坑也坑......
【题目描述】
给你一个n种面值的货币系统,求组成面值为m的货币有多少种方案。
【输入】
第一行输入两个正整数n和m,用空格隔开,分别表示货币系统的面值种数和要组成的总面值。
以下n行,每行输入一个正整数,表示货币系统的面值。
【输出】
一行一个数,表示组成目标面值的方案总数。
【输入示例】
3 10
1
2
5
【输出示例】
10
我第一眼看到这道题竟然想到了动规(可喜可贺可喜可贺)
dp[i]=sum(dp[i-面值1],dp[i-面值2]...dp[i-面值n])
但是!我一开始是这么做的
1 #include<iostream> 2 using namespace std; 3 long long n,m; 4 long long money[18713]; 5 long long dp[10013]; 6 int main() 7 { 8 //freopen("money.in","r",stdin); 9 //freopen("money.out","w",stdout); 10 cin>>n>>m; 11 for(long long i=1;i<=n;i++) 12 { 13 cin>>money[i]; 14 } 15 dp[0]=1; 16 for(long long i=1;i<=m;i++) 17 { 18 for(long long j=1;j<=n;j++) 19 { 20 dp[i]=dp[i]+dp[i-money[j]]; 21 } 22 } 23 if(n==0&&m==0) 24 { 25 cout<<0; 26 } 27 else 28 { 29 cout<<dp[m]; 30 } 31 return 0; 32 }
看着没有任何问题!对吧?对吧?
但是!你输一下样例就会发现......它特么输出128(呵)
因此我考试的时候交了道深搜然后果不其然的T了......只拿了六十分
如果你输入2、3、1、2的话
你枚举一下,一共有两种可能:1、1、1,1、2
但是你让它算的话,它是把1、2和2、1算成两种可能的。
所以我们要把n踹到外面
1 #include<iostream> 2 using namespace std; 3 long long n,m; 4 long long money[18713]; 5 long long dp[10013]; 6 int main() 7 { 8 //freopen("money.in","r",stdin); 9 //freopen("money.out","w",stdout); 10 cin>>n>>m; 11 for(long long i=1;i<=n;i++) 12 { 13 cin>>money[i]; 14 } 15 dp[0]=1; 16 for(long long i=1;i<=n;i++) 17 { 18 for(long long j=1;j<=m;j++) 19 { 20 dp[j]=dp[j]+dp[j-money[i]]; 21 } 22 } 23 if(n==0&&m==0) 24 { 25 cout<<0; 26 } 27 else 28 { 29 cout<<dp[m]; 30 } 31 return 0; 32 }
这样就OK了
在暴风雨中低着头,是为了不让雨水模糊风雨后眼中的彩虹。