题意:有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 }