洛谷 P5020 货币系统 题解

每日一题 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 }

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

猜你喜欢

转载自www.cnblogs.com/handsome-zyc/p/11483766.html