思路:
图片来自抓不住Jerry的Tom,那么我们将所有浓度预先减去k,题目变成抽取最少的二氧化碳使得总和为0,就是背包问题,那么最多需要多少瓶呢?1000瓶,可以这样考虑,给定的浓度为 b ,如果有一个比他小的浓度 a 和一个比他大的浓度 c 。那么最多需要(b-a)升 c 、 (c-b)升 a 就可以得到浓度 b 。那么答案最大即为 c - a. 所以肯定小于1000,加个bitset优化一下就行了。
因为-1000 <= ai-n <= 1000,所以超出的部分可以忽略。
# include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6;
bitset<2003>b[2];
int a[maxn+3];
int main()
{
int n, k, t=1;
scanf("%d%d",&k,&n);
for(int i=0; i<n; ++i)
{
scanf("%d",&a[i]);
a[i] -= k;
}
sort(a, a+n);
n = unique(a, a+n) - a;
b[0].set(1000);
for(int i=1; i<=1000; ++i)
{
for(int j=0; j<n; ++j)
{
if(a[j] < 0)
b[t] |= b[1-t] << (-a[j]);
else
b[t] |= b[1-t] >> a[j];
}
if(b[t][1000])
return 0*printf("%d\n",i);
t = 1-t;
b[t].reset();
}
puts("-1");
return 0;
}
# include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6;
queue<int>q;
int a[maxn+3], b[maxn+3];
int main()
{
int n, k, t=1;
scanf("%d%d",&k,&n);
for(int i=0; i<n; ++i)
{
scanf("%d",&a[i]);
a[i] -= k;
}
sort(a, a+n);
n = unique(a, a+n) - a;
memset(b, -1, sizeof(b));
b[1000] = 0;
q.push(1000);
while(!q.empty())
{
int top = q.front();
q.pop();
for(int i=0; i<n; ++i)
{
if(top+a[i] == 1000)
return 0*printf("%d\n",b[top]+1);
else if((top+a[i]>=0 || top+a[i]<=2000)&&b[top+a[i]]==-1)
b[top+a[i]] = b[top] + 1, q.push(top+a[i]);
}
}
puts("-1");
return 0;
}
上面是BFS写法。