传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6685
比赛的时候没过,队友重写一发过了。
经过对数据的调试,发现了一些问题
我已开始只开到20开始爆搜,经验证发现不行要开到30爆搜
后来还发现一些问题。。。。
比如我们在最大值/100*100-200的位置为基准bas,大于bas就减去bas再除10,说明这个是要通过10 20 50 100凑出来的。
但是<=bas的要和他们分开
因为小于bas的%100=10的可能是通过大于bas的凑出110 或者 210 得到的,所以在dfs要对这种情况经过特盘。
#include<bits/stdc++.h>
#define maxl 110
using namespace std;
int n;
long long sum,ans,mx,bas;
long long w[maxl];
int t[5]={0,10,5,2,1};
int a[maxl],f[maxl],fa[maxl],fbas[maxl];
bool flag,ok;
inline bool cmp(const int &x,const int &y) {return x>y;}
inline void prework()
{
flag=true;
for(int i=0;i<=30;i++)
f[i]=0,fbas[i]=0;
scanf("%d",&n);sum=0;
mx=0;
for(int i=1;i<=n;i++)
scanf("%lld",&w[i]);
for(int i=1;i<=n;i++)
{
if(w[i]%10!=0)
{
flag=false;
return;
}
mx=max(w[i],mx);
}
sort(w+1,w+1+n,cmp);
}
inline void jug(int up)
{
for(int i=1;i<=30;i++)
fa[i]=0;
fa[0]=1;
for(int i=1;i<=up;i++)
for(int j=30;j-a[i]>=0;j--)
if(fa[j-a[i]])
fa[j]=1;
for(int i=1;i<=30;i++)
{
if(f[i] && !fa[i])
return;
if(i<=10 && fbas[i] && !fa[i] && !fa[i+10] && !fa[i+20])
return;
if(i<=20 && fbas[i] && !fa[i] && !fa[i+10])
return;
}
ok=true;
}
inline void dfs(int k,int last,int up)
{
for(int i=last;i<=4 && !ok;i++)
{
a[k]=t[i];
if(k==up)
jug(up);
else
dfs(k+1,i,up);
a[k]=0;
}
}
inline void mainwork()
{
if(!flag)
return;
bas=(mx/100-2)*100;
bas=max(0ll,bas);
for(int i=1;i<=n;i++)
{
if(w[i]<=bas)
fbas[(w[i]/10)%10]=1;
else
f[(w[i]-bas)/10]=1;
}
ans=bas/100;
ok=false;
for(int i=1;i<=15;i++)
{
dfs(1,1,i);
if(ok)
{
ans=ans+i;
break;
}
}
}
inline void print()
{
if(flag)
printf("%lld\n",ans);
else
puts("-1");
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("out.out","w",stdout);
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}