题目链接:http://codeforces.com/contest/788/problem/C
一看就不能暴力$DP$,我们可以将浓度的合并操看作为在追逐一高度,每次操作前这个高度都会向上走$n$,每次加入一定浓度的汽水就增加了相应的高度$a_i$,由于每次都是进行相同的转移,所以一旦高度差的绝对值大于了$1000$,这个状态就没有了意义(因为一定会有等价的状态比他更好),剪枝一下。所以每一次转移就是${O(n*min(k,1000))}$的。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 #include<ctime> 9 #include<map> 10 using namespace std; 11 #define maxn 10010 12 #define llg long long 13 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 14 llg n,m,k,a[maxn]; 15 bool xian[maxn]; 16 map<llg,bool>ma; 17 vector<llg>f,nf; 18 inline int getint() 19 { 20 int w=0,q=0; char c=getchar(); 21 while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 22 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; 23 } 24 25 int main() 26 { 27 // yyj("C"); 28 cin>>n>>k; 29 for (llg i=1;i<=k;i++) 30 { 31 llg x=getint(); 32 if (xian[x]) continue; 33 xian[x]=1; 34 a[++m]=x; 35 } 36 f.push_back(0); 37 for (llg tim=1;;tim++) 38 { 39 if ((double)clock()/CLOCKS_PER_SEC>0.91) break; 40 ma.clear(); 41 llg w=f.size(); nf.clear(); 42 for (llg i=0;i<w;i++) 43 { 44 llg val=f[i]; 45 val-=n; 46 for (llg j=1;j<=m;j++) 47 { 48 llg nval=val+a[j]; 49 if (nval==0) 50 { 51 cout<<tim; 52 return 0; 53 } 54 if (nval>2000 || nval<-2000) continue; 55 if (ma[nval]) continue; 56 ma[nval]=1; 57 nf.push_back(nval); 58 } 59 } 60 f.clear(); 61 w=nf.size(); 62 for (llg i=0;i<w;i++) f.push_back(nf[i]); 63 } 64 cout<<-1; 65 return 0; 66 }