混合调酒
思路:
假设共用了m杯酒,酒精含量分别为b1,b2…bm
b1+…+bm=m*n
b1+…+bm=n+n+…+n(m个)
(b1-n)+(b2-n)+…+(bm-n)=0
即:将所有的酒精含量减去n后,寻找最少的数字使他们的和为0
我们把数字和(-1000到1000)当作节点,可以使用的酒精含量当作边(边权为1),跑从0到0的最短路(也就是bfs)即可。注意显然存在一条任何时候数字和绝对值不超过1000的路径,所以(如果有解)一定能找到解。
#include<stdio.h>
#include<cstring>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
queue <int> state ;
int n,k,S=0,a[200010],dis[200010],se[200010];
int main()
{
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
int x;
scanf("%d",&x);
a[x]=1;
}
memset(dis,INF,sizeof(dis));
state.push(S),dis[S]=0,se[S]=1;
while(!state.empty())
{
int u=state.front(),cur=state.front();
if(u==0) cur=1005;
state.pop(),se[u]=0;
for(int i=0;i<=1000;i++)
{
if(!a[i]) continue ;
int v=i-n+cur;
if(v>0 && v<2007 && dis[v]>dis[u])
{
dis[v]=dis[u]+1;
if(!se[v])
se[v]=1,state.push(v);
}
}
}
if(dis[1005]==INF) printf("-1\n");
else printf("%d\n",dis[1005]);
return 0;
}