【HDOJ6685】Rikka with Coin(DP)

题意:有10,20,30,100四种硬币,每种数量无限,给定n个a[i],问能组成所有a[i]的硬币的最小总数量

n<=1e2,a[i]<=1e9

思路:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef unsigned int uint;
 5 typedef unsigned long long ull;
 6 typedef pair<int,int> PII;
 7 typedef pair<ll,ll> Pll;
 8 typedef vector<int> VI;
 9 typedef vector<PII> VII;
10 #define N  310000
11 #define M  4100000
12 #define fi first
13 #define se second
14 #define MP make_pair
15 #define pi acos(-1)
16 #define mem(a,b) memset(a,b,sizeof(a))
17 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
18 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
19 #define lowbit(x) x&(-x)
20 #define Rand (rand()*(1<<16)+rand())
21 #define id(x) ((x)<=B?(x):m-n/(x)+1)
22 #define ls p<<1
23 #define rs p<<1|1
24 
25 const ll MOD=1e9+7,inv2=(MOD+1)/2;
26       double eps=1e-6;
27       int INF=1e9;
28       int da[4]={-1,1,0,0};
29       int db[4]={0,0,-1,1};
30 
31       int vis[3][200],a[N],b[4],n;
32 
33 int read()
34 {
35    int v=0,f=1;
36    char c=getchar();
37    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
38    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
39    return v*f;
40 }
41 
42 int isok()
43 {
44     mem(vis,0);
45     int m=b[1]+b[2]*2+b[3]*5;
46     rep(i,0,b[1]) vis[0][i]=1;
47     rep(i,0,b[2])
48      rep(j,0,m)
49       if(vis[0][j]) vis[1][j+i*2]=1;
50     rep(i,0,b[3])
51      rep(j,0,m)
52       if(vis[1][j]) vis[2][j+i*5]=1;
53     int ans=0;
54     rep(i,1,n)
55     {
56         int t=INF;
57         rep(j,0,m)
58          if(vis[2][j]&&(a[i]-j*10)%100==0) t=min(t,(a[i]-j*10)/100);
59         if(t==INF) return -1;
60         ans=max(ans,t);
61     }
62     return ans;
63 }
64 
65 int main()
66 {
67     //freopen("1.in","r",stdin);
68     //freopen("1.out","w",stdout);
69 
70     int cas;
71     scanf("%d",&cas);
72 
73     while(cas--)
74     {
75         n=read();
76         rep(i,1,n) a[i]=read();
77 
78         int ans=INF;
79         for(b[1]=0;b[1]<=1;b[1]++)
80          for(b[2]=0;b[2]<=4;b[2]++)
81           for(b[3]=0;b[3]<=1;b[3]++)
82           {
83               int t=isok();
84               if(t!=-1) ans=min(ans,b[1]+b[2]+b[3]+t);
85           }
86 
87         if(ans==INF) printf("-1
");
88          else printf("%d
",ans);
89 
90     }
91 
92     return 0;
93 }
原文地址:https://www.cnblogs.com/myx12345/p/11666833.html