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 } 

 

posted @ 2019-08-18 00:10  毛炯人  阅读(173)  评论(0编辑  收藏  举报