P1474货币系统
这是USACO的一道DP题,难度是提高—。
这道题是告诉我们货币种类,问你用这些货币组成一个面值最大有多少种方案。第一眼看上去想用dfs记忆化,随后发现其实这个题很类似于完全背包,可以取无线件,但是他的转移方程与普通的不同。而我一开始并没有静下心来去思考,没有想出来。最后得出了结论dp[j]=dp[j]+dp[j-coin[i]]。最后输出dp[T]即可。
1.认真推导状态转移方程,别老想着套用公式,必须举几个例子来推导出来,不要去畏惧困难,不要去怕麻烦
2.注意循环变量i于j别混淆,尤其是++
3.根据不同题意确定不同dp[]代表的含义
4.要对于dp[]进行初始化,比如这个题dp[0]=1;要考虑周全
代码
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<cmath> #include<iomanip> #include<algorithm> #define N 1000001 #define ll long long using namespace std; int T,n; int coin[N]; ll ans=0; ll dp[N];//当前面额存在最大方案数 int main(){ cin>>n>>T; for(int i=1;i<=n;i++){ scanf("%d",&coin[i]); } dp[0]=1; for(int i=1;i<=n;i++){ for(int j=coin[i];j<=T;j++){ dp[j]=dp[j]+dp[j-coin[i]]; } } cout<<dp[T]; return 0; }
待到oi十一月,我花开后百花杀。