P5020货币系统
这个题是2018提高组真题,是一道看不出是背包的背包题。
题干特别长,甚至有些没看懂。题意为给出一组货币面值,然后从这里面用最少的面值数量取代原先的面值。比如3,6直接用3表示。一开始想到了小凯的疑惑想两两一组求最高不能表示的数,发现根本不是。发现只要看原先的面值是否可以用比他小的面值来替代,那么这个面值就可以取消了,顿时发现这是一个完全背包!容量为最大的数,dp[]表示最多能被几张已有面值代替,cash就表示体积,那么状态转移方程就是dp[j]=dp[j],dp[j-cash[i]]+1;到最后再统计dp[cash[i]]=1的就代表无法被代替,累加输出即可。再在上面进行一个初始化即AC。
1.审题要专心,如果看不懂就结合样例,去上下文进行判断,别羽墨。
2.初始化时,这里的dp[i]不可以初始化为0,因为方程是+1,所以有好多表示不出来的可能会+1,注意长度。
3.要把复杂的动态规划往背包等有模型的上面转化,但也不可以抓住不放。eg.大凯的疑惑
4.memset的长度是字节,如果用的话要*内存。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 using namespace std; 7 int T; 8 int n,m; 9 int cash[2500005]; 10 int dp[2500005];//完全背包 11 int book[2500005]; 12 int main(){ 13 cin>>T; 14 for(int i=1;i<=T;i++){ 15 cin>>n; 16 m=0; 17 for(int i=1;i<=n;i++){//读入 18 cin>>cash[i]; 19 } 20 sort(cash+1,cash+n+1);//排序 21 for(int i=0;i<=cash[n];i++) 22 dp[i]=-555555; 23 for(int i=1;i<=n;i++){ 24 dp[cash[i]]=1; 25 } 26 for(int i=1;i<=n;i++){//完全背包 27 for(int j=cash[i];j<=cash[n];j++){ 28 dp[j]=max(dp[j],dp[j-cash[i]]+1); 29 } 30 } 31 for(int i=1;i<=n;i++){ 32 if(dp[cash[i]]==1){ 33 //cout<<cash[i]<<endl; 34 m++; 35 } 36 } 37 cout<<m<<endl; 38 } 39 return 0; 40 }
待到oi十一月,我花开后百花杀。