• 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 } 
  • 相关阅读:
    二叉树(链表形式)
    判断一个非空单链表是否是递增有序的
    指针的异或运算可用于交换两个变量的值
    JavaScript导论
    JavaScript语言的历史
    分享一个分页控件的实现思路
    MVC还是MVVM?或许VMVC更适合WinForm客户端
    基于NPOI的Excel数据导入
    一段用于地址清洗的代码
    模块3之手机号码格式的校验
  • 原文地址:https://www.cnblogs.com/china-mjr/p/11371054.html
Copyright © 2020-2023  润新知