1954: 吃麵包(列舉,技巧)
阿新 • • 發佈:2019-01-30
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; } } }