洛谷 P5020 货币系统 题解

匿名 (未验证) 提交于 2019-12-02 23:59:01

每日一题 day7 打卡

Analysis

完全背包+筛法

只用完全背包会超时,所以要用筛法的思想来优化:筛去所有可以用已知货币系统中的面值表示出来的金额

80分 不用筛法

 1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 #define maxn 100+10  6 #define maxnum 25000+10  7 #define INF 2147483647/2-1  8 using namespace std;  9 inline int read()  10 { 11     int x=0; 12     bool f=1; 13     char c=getchar(); 14     for(; !isdigit(c); c=getchar()) if(c=='-') f=0; 15     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; 16     if(f) return x; 17     return 0-x; 18 } 19 inline void write(int x) 20 { 21     if(x<0){putchar('-');x=-x;} 22     if(x>9)write(x/10); 23     putchar(x%10+'0'); 24 } 25 int T; 26 int n,ans; 27 int a[maxn],dp[maxnum]; 28 inline bool check(int x) 29 { 30     memset(dp,0,sizeof(dp)); 31     for(int i=1;i<x;i++) 32         for(int j=a[i];j<=a[x];j++) 33             dp[j]=max(dp[j-a[i]]+a[i],dp[j]); 34     if(dp[a[x]]==a[x]) return false; 35     return true; 36 } 37 int main() 38 { 39     T=read(); 40     while(T--) 41     { 42         memset(dp,0,sizeof(dp)); 43         n=read(); 44         ans=n; 45         for(int i=1;i<=n;i++) a[i]=read(); 46         sort(a+1,a+n+1); 47         for(int i=2;i<=n;i++) if(check(i)==false) ans--; 48         write(ans); 49         printf("\n"); 50     } 51     return 0; 52 }

100分 筛法

mark[i]=0 表示i面值的钱不能被凑出来
mark[i]=1 表示i面值的钱可以被凑出来
mark[i]=2 表示i面值的钱是货币系统中本来就有

 1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 #define maxn 100+10  6 #define maxnum 25000+10  7 #define INF 2147483647/2-1  8 using namespace std;  9 inline int read()  10 { 11     int x=0; 12     bool f=1; 13     char c=getchar(); 14     for(; !isdigit(c); c=getchar()) if(c=='-') f=0; 15     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; 16     if(f) return x; 17     return 0-x; 18 } 19 inline void write(int x) 20 { 21     if(x<0){putchar('-');x=-x;} 22     if(x>9)write(x/10); 23     putchar(x%10+'0'); 24 } 25 int T; 26 int n,ans; 27 int a[maxn],mark[maxnum]; 28 int main() 29 { 30     T=read(); 31     while(T--) 32     { 33         memset(mark,0,sizeof(mark)); 34         n=read(); 35         ans=n; 36         for(int i=1;i<=n;i++) 37         { 38             a[i]=read(); 39             mark[a[i]]=2; 40         }  41         sort(a+1,a+n+1); 42         for(int i=1;i<=a[n];i++) 43             if(mark[i]>0) 44                 for(int j=1;j<=n;j++) 45                 { 46                     if(i+a[j]<=a[n]) mark[i+a[j]]=1; 47                     else break; 48                 } 49         for(int i=2;i<=n;i++) if(mark[a[i]]==1) ans--;     50         write(ans); 51         printf("\n");     52     } 53     return 0; 54 }

请各位大佬斧正(反正我不认识斧正是什么意思)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!