题意:给6个纸币面额,求出用最少的这6个纸币凑出1-100的面值,求这1-100需要的纸币数种的最大值。
解题思路:2个完全背包。
注意点:
(1)可以相加也可以想减,
(2)注意上限,考虑极端数据1 95 96 97 98 99。
貌似计算出48次数最多,大概估计不超过30次,所以dp开30*100,如果懒得考虑,直接开100*100。
AC代码:
View Code
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define maxn 3000 #define INF 1<<29 int w[7],dp[3003]; int main() { int i, j, cas; scanf("%d",&cas); while(cas--) { fill(dp+1,dp+maxn+1,INF); dp[0]=0; for(i=1;i<=6;i++) scanf("%d",&w[i]); //以下是2个完全背包,加和减。 for(i=1;i<=6;i++) for(j=w[i];j<=maxn;j++) //注意:循环的顺序,不清楚的自己手推一下 dp[j]=min(dp[j],dp[j-w[i]]+1);//注意:别看代码里是减,这里是加上价格w[i] for(i=1;i<=6;i++) for(j=maxn-w[i];j>=0;j--) //注意:循环的顺序,不清楚的自己手推一下 dp[j]=min(dp[j],dp[j+w[i]]+1);//注意:别看代码里是加,这里是减去价格w[i] double ave=0; int ans=0; for(i=1;i<=100;i++) { ave+=dp[i]; ans=max(ans,dp[i]); } printf("%.2f %d\n",ave/100,ans); } return 0; }