洛谷 P1412 經營與開發
P1412 經營與開發
題目描述
4X概念體系,是指在PC戰略遊戲中一種相當普及和成熟的系統概念,得名自4個同樣以“EX”為開頭的英語單詞。
eXplore(探索)
eXpand(拓張與發展)
eXploit(經營與開發)
eXterminate(征服)
——維基百科
今次我們著重考慮exploit部分,並將其模型簡化:
你駕駛著一臺帶有鉆頭(初始能力值w)的飛船,按既定路線依次飛過n個星球。
星球籠統的分為2類:資源型和維修型。(p為鉆頭當前能力值)
1.資源型:含礦物質量a[i],若選擇開采,則得到a[i]*p的金錢,之後鉆頭損耗k%,即p=p*(1-0.01k)
2.維修型:維護費用b[i],若選擇維修,則支付b[i]*p的金錢,之後鉆頭修復c%,即p=p*(1+0.01c)
註:維修後鉆頭的能力值可以超過初始值(你可以認為是翻修+升級)
金錢可以透支。
請作為艦長的你仔細抉擇以最大化收入。
輸入輸出格式
輸入格式:
第一行4個整數n,k,c,w。
以下n行,每行2個整數type,x。
type為1則代表其為資源型星球,x為其礦物質含量a[i];
type為2則代表其為維修型星球,x為其維護費用b[i];
輸出格式:
一個實數(保留2位小數),表示最大的收入。
輸入輸出樣例
輸入樣例#1:5 50 50 10 1 10 1 20 2 10 2 20 1 30
375.00
說明
【數據範圍】
對於30%的數據 n<=100
另有20%的數據 n<=1000;k=100
對於100%的數據 n<=100000; 0<=k,c,w,a[i],b[i]<=100;保證答案不超過10^9
“依次飛過n個星球”,第一反應就是動態規劃,然後驗證下無後效性即可。
這題關鍵點為狀態的設計。
<Method 1>
F[i][x]表示到達第i個星球,且鉆頭能力值為x的最大收入值。
x因為是實數,所以要取一定的精度。對於數值範圍都在100的本題,n在10左右的時候毫無壓力。
時空復雜度:O(nx) x為精度範圍。
期望得分:10-30;
<Method 2>
F[i][x][y]表示到達第i個星球,且之前開采過x次,維修過y次。
因為本題開采和維修對鉆頭的影響都是定值。所以鉆頭能力就是w*k^x*c^y
時空復雜度:O(n^3)
期望得分:30
<Method 3>
對於20% k=100的數據,鉆頭開采一次就永久損壞了。所以只需記錄維修過幾次即可。
時空復雜度:O(n^2)
期望得分:20 (配合Method 2為50)
<Method 4>
與Method 2一樣的狀態設計。但是x,y的範圍不需要與n相同。因為在隨機情況下,開采和維修的次數寥寥無幾(結合次冪考慮)。
時空復雜度:O(nxy) x,y為選手選擇的範圍
期望得分:30-80
<Method 5>
與Method 2一樣的狀態設計,但是使用BFS來進行DP過程,這樣就不會遍歷到沒有被訪問到的狀態,同時選手可以自己加上一些簡單的貪心判斷來減少狀態數量。
時空復雜度:O(?)
期望得分:70-100
<Method 6>
與前5種做法截然不同。前5種做法的最大瓶頸就是“當前鉆頭能力”,下面我們嘗試不存儲“當前鉆頭能力”。
F[i]表示前i個星球的最優收入。很明顯這是不行的,因為當前鉆頭能力會切實影響到後面的過程,不嚴謹的說,當前鉆頭能力有“後效性”。
但是這個當前鉆頭能力對後程的影響無非就是乘上一個數值。(就好像初始鉆頭能力為w,實際上你可以按1來做,最後再把ans乘上w)。
正難則反,F[i]表示第i--n個星球的最優收入,且假設從第i個星球開始時鉆頭能力為1。換句話說,這樣的狀態設計,規定了一個參考系。
轉移過程就變得簡單:如果在第i個星球開采,那麽第i+1--n個星球的初始鉆頭能力就是1*(1-0.01k)。換句話說,就是F[i+1]*(1-0.01k)。
所以F[i]=max{F[i+1],F[i+1]*(1-0.01k)+a[i]}
對於維護型星球,大同小異。就系數和代價的正負而已。
觀察方程,F[i]=max{F[i+1],F[i+1]*(1-0.01k)+a[i]}
實際上就是取下i+1--n的最值而已,所以這題實際上就成了貪心。
#include<cstdio> #include<iostream> using namespace std; #define N 100010 int n,t[N],a[N]; double k,c,w,ans=0; int main(){ scanf("%d%lf%lf%lf",&n,&k,&c,&w); k=1-0.01*k;c=1+0.01*c;//關鍵處理 for(int i=1;i<=n;i++) scanf("%d%d",t+i,a+i); for(int i=n;i>=1;i--){ if(t[i]==1)ans=max(ans,ans*k+a[i]); else ans=max(ans,ans*c-a[i]); } printf("%.2lf",ans*w); return 0; }
洛谷 P1412 經營與開發