图论训练 混合调酒 [最短路][好题]

6 篇文章 0 订阅
2 篇文章 0 订阅

这道题果然质量(防AK了………………)

混合调酒(d.cpp,1s,256MB)

【描述】
酒吧里有 k 种鸡尾酒,每种的酒精含量(体积分数)为 ai/1000 。你想喝到酒精含量为 n/1000 的酒,因此你想要把一些鸡尾酒混合起来以达到目的。混合后酒精含量的定义为所有参与混合的鸡尾酒中酒精的体积和除以所有参与混合的鸡尾酒的体积和。你想知道最少需要购买多少杯鸡尾酒才能满足条件。假设每种鸡尾酒都无限供应,每杯酒的体积都是相同的。
【输入】
第一行两个整数n,k,意义如上所述。
第二行k个整数a_i,表示每种酒的酒精含量。不同酒的酒精含量可能相同。
【输出】
一行一个整数,表示至少需要购买的鸡尾酒杯数。如果无法满足条件,输出-1。
【样例输入】
50 2
100 25
【样例输出】
3
【样例解释】
购买1杯第一种鸡尾酒,2杯第二种鸡尾酒,混合起来即可。
【限制与约定】
对于30%的数据,k<=2。
对于100%的数据,0<=n,a_i<=1000,1<=k<=100000。

思考

假设共用了m杯酒,酒精含量分别为 b1,b2...bm
b1+...+bm=mn
b1+...+bm=n+n+...+n(m)
(b1n)+(b2n)+...+(bmn)=0
即:将所有的酒精含量减去n后,寻找最少的数字使他们的和为0
我们把数字和 10001000 当作节点,可以使用的酒精含量当作边(边权为1),跑从0到0的最短路(也就是bfs)即可。注意显然存在一条任何时候数字和绝对值不超过1000的路径,所以(如果有解)一定能找到解。
看起来很难,然而代码简单得一匹…………我是蒟蒻。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define maxn 2010
bool v[maxn],a[maxn];
int n,k,d[maxn];
int sta[maxn];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1; i<=k; i++)
    {
        int p; scanf("%d",&p);
        a[p]=true;
    }
    memset(d,0x3f,sizeof(d));
    d[1005]=0;
    int ta=1,fr=1; sta[1]=1005;
    while(ta<=fr)
    {
        int cur=sta[ta++];
        int cd=d[cur];
        for(int i=0; i<=1000; i++)
            if(a[i])
            {
                int re=i-n;
                if(cur+re>0 && cur+re<2007 && !v[cur+re])
                {
                    v[cur+re]=true;
                    d[cur+re]=cd+1;
                    sta[++fr]=cur+re;
                }
            }
    }
    if(d[1005]==0) puts("-1");
    else printf("%d\n",d[1005]);
    return 0;
}

由于边权为1,所以bfs就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值