2018 FJUT ACM校賽L題 外傳:魔王打工記(三)
外傳:魔王打工記(三)
TimeLimit:1000MS MemoryLimit:128MB 64-bit integer IO format:%lld Problem Description靠著小明的朝五晚九地經營共享單車,魔王堡的總算熬過了這一個月。但是好景不長,共享單車市場競爭的太激烈,小明的公司已經開始虧損了,再這麽下去吃棗藥丸。
統計局的工資可能都不夠虧的。為保住自己褲衩不被當掉,Home_W正苦苦思索著策略,這時網上突然出現了阿裏巴巴用區塊鏈養豬的新聞,Home_W看到現在農業這麽火,靈機一動,決定辭掉統計局的工作,回農村種地,用大數據分析和人工智能搞生態農業。
現在Home_W要下鄉種地n天,每天他都可以從地中收獲到a[i]的蔬菜。同時第i天蔬菜的價格為b[i]。
Home_W 有一個發大財的心,所以他可能不會立即賣掉剛收獲上來的蔬菜,而是會屯幾天的菜,等到價格高了再一次性清倉全部賣掉。
但是每單位蔬菜每屯一天要花費1的電費用於制冷,比如,若單位電費為1,第1、2、3天得到蔬菜分別是3,2,1 那麽把這些蔬菜屯到第4天再賣,要花費3*3+2*2+1*1=14電費。我們偉大Home_W 大魔王用大數據技術和魔力的組合完美預測出了這n天中,每天他能收獲的蔬菜數量和蔬菜每天的價格。於是他采
取了最優策策略來賣菜,那麽n天結束後他最多能賺到多少錢?
Input
單組數據,第一行是一個整數n代表天數
接下來一行 有n個數字 a1,a2,a3……an 代表每天收獲上來的蔬菜的數量
再接下一行 有n個數 字 b1,b2,b3……bn 代表蔬菜每天的價格
1<=n<=5*105
0<ai,bi<=105
Output輸出一個整數,代表如果采取最優策略來賣菜,那麽n天結束後Home_W最多能賺到錢的數量.
註意賣的時候必須賣光,不能留任何蔬菜
SampleInput8 7 9 8 3 5 5 6 9 4 9 4 3 3 7 4 5SampleOutput
318
hint:分別在第二天,第六天,第八天賣出所有的蔬菜
/**
思路:
因為最後一天肯定是得賣出的,所以以最後一天為
最後一個狀態,往前面推。假設最後一天的價值為
cost【n-1】,那麽前一個狀態對應的價值就會有兩個
一個是cost【n-2】,一個是cost【n-1】-1;從兩個狀態
中我們當然是要選擇大的那個。如果說cost【n-2】大於cost【n-1】-1;
那麽我們肯定得選擇在這一天賣出,不能存到cost【n-1】再賣出。
然後每次賣出就改變比較的值,往前面比較。你可能會問為什麽要改變。
因為cost【n-2】的狀態肯定大於cost【n-1】-1,那麽再往前推一步,
cost【n-2】-1肯定大於cost【n-1】-2;所以保留cost【n-2】去與
cost【n-3】進行比較就可以了。
我們可以先標記在哪一天賣出,最後進行一次O(n)的計算就可以得出答案了。
**/
附上代碼:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int MAXN = 5*1e5+5; ll gas[MAXN]; ll cost[MAXN]; int flag[MAXN]; /** 思路: 因為最後一天肯定是得賣出的,所以以最後一天為 最後一個狀態,往前面推。假設最後一天的價值為 cost【n-1】,那麽前一個狀態對應的價值就會有兩個 一個是cost【n-2】,一個是cost【n-1】-1;從兩個狀態 中我們當然是要選擇大的那個。如果說cost【n-2】大於cost【n-1】-1; 那麽我們肯定得選擇在這一天賣出,不能存到cost【n-1】再賣出。 然後每次賣出就改變比較的值,往前面比較。你可能會問為什麽要改變。 因為cost【n-2】的狀態肯定大於cost【n-1】-1,那麽再往前推一步, cost【n-2】-1肯定大於cost【n-1】-2;所以保留cost【n-2】去與 cost【n-3】進行比較就可以了。 我們可以先標記在哪一天賣出,最後進行一次O(n)的計算就可以得出答案了。 **/ int main() { int n; while(~scanf("%d",&n)) { memset(gas,0,sizeof(gas)); memset(cost,0,sizeof(cost)); memset(flag,0,sizeof(flag)); for(int i=0; i<n; i++) scanf("%lld",&gas[i]); for(int i=0; i<n; i++) scanf("%lld",&cost[i]); flag[n-1]=1;///初始標記,最後一天肯定賣出 int ans=cost[n-1];///轉移的價格 for(int i=n-2;i!=-1;i--) { if(ans-1>cost[i]) { ans--;///如果價值依舊大,那麽往前接著轉移 } else { ans=cost[i];///如果價值小的話,進行改變轉移值 flag[i]=1;///標記賣出,再往前轉移 } } ll sum,num; sum=0; num=0; for(int i=0;i<n;i++)///計算答案 { if(flag[i]) { sum+=(num+gas[i])*cost[i]; num=0; } else { num+=gas[i]; sum-=num; } } printf("%lld\n",sum); } return 0; }
2018 FJUT ACM校賽L題 外傳:魔王打工記(三)