1. 程式人生 > >2018 FJUT ACM校賽L題 外傳:魔王打工記(三)

2018 FJUT ACM校賽L題 外傳:魔王打工記(三)

cost size turn 一次 clas 選擇 output pro sum

外傳:魔王打工記(三)

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最多能賺到錢的數量.

註意賣的時候必須賣光,不能留任何蔬菜

SampleInput
8
7 9 8 3 5 5 6 9
4 9 4 3 3 7 4 5 
SampleOutput
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題 外傳:魔王打工記(三)