1. 程式人生 > >1954: 吃麵包(列舉,技巧)

1954: 吃麵包(列舉,技巧)

Author

csust

思路:

這道題因為只有兩個物品,所以我們容易想到列舉一個物品的個數,另一個物品的個數也就也就確定了,維護下最大值就好了,但是呢,由於資料量很大,裸的列舉很容易超時,那麼我們可以想到縮小列舉的邊界,那麼怎麼縮小呢,一種容易想到的就是每一種最多的列舉量是min(all/cost1,all/cost2),但是這也會存在一個問題,就是當cost1和cost2都很小的時候,那麼列舉量還是很大,那麼怎麼辦呢,有一個技巧就是,我們有一個等式,就是 cost1*cost2 = cost2*cost1,這是花費相同的時候,那麼然後再去計算此時兩種的價值為cost2*pay1和,cost1*pay2,如果前者比較大的話那麼第二種物品最多拿cost1-1個,要不然的話,cost1個物品都可以由第一種物品代替,如果第二種較大的話,就是第一種最多選cost2-1個。。。。。最後說一句,列舉的時候如果裸的列舉會超,想辦法減小列舉的邊界(這裡是抓住了當花費相同的時候)。

ac程式碼:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<map>
#include<vector>
#include<sstream>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+10;
long long all,pay1,pay2,cost1,cost2;

int main()
{
    while(~scanf("%lld%lld%lld%lld%lld",&all,&pay1,&pay2,&cost1,&cost2))
    {
       if(cost1>cost2)
            swap(cost1,cost2),swap(pay1,pay2);
        LL ans = -1;
       if((all/cost2)<maxn)
       {
           LL num = all/cost2;
            for(int i = 0 ;i<=num;i++)
            {
                LL pre = all - i*cost2;
                ans = max(i*pay2+(pre/cost1)*pay1,ans);
            }
            cout<<ans<<endl;
       }
       else
       {
           LL ans2 = -1;
           for(int i = 0;i <= cost2;i++)
           {
               LL pre = all - i*cost1;
               ans2 = max(i*pay1+(pre/cost2)*pay2,ans2);
           }for(int i = 0;i <= cost1;i++)
           {
               LL pre = all - i*cost2;
               ans2 = max(i*pay2+(pre/cost1)*pay1,ans2);
           }
           cout<<ans2<<endl;
       }
    }
}