題目描述
小新正在玩一個簡單的電腦遊戲。
遊戲中有一條環形馬路,馬路上有 n 個機器人工廠,兩個相鄰機器人工廠之間由一小段馬路連線。小新以某個機器人工廠為起點,按順時針順序依次將這 n 個機器人工廠編號為1~n,因為馬路是環形的,所以第 n 個機器人工廠和第 1 個機器人工廠是由一段馬路連線在一起的。小新將連線機器人工廠的這 n 段馬路也編號為 1~n,並規定第 i 段馬路連線第 i 個機器人工廠和第 i+1 個機器人工廠(1≤i≤n-1),第 n 段馬路連線第 n 個機器人工廠和第 1個機器人工廠。
遊戲過程中,每個單位時間內,每段馬路上都會出現一些金幣,金幣的數量會隨著時間發生變化,即不同單位時間內同一段馬路上出現的金幣數量可能是不同的。小新需要機器人的幫助才能收集到馬路上的金幣。所需的機器人必須在機器人工廠用一些金幣來購買,機器人一旦被購買,便會沿著環形馬路按順時針方向一直行走,在每個單位時間內行走一次,即從當前所在的機器人工廠到達相鄰的下一個機器人工廠,並將經過的馬路上的所有金幣收集給小新,例如,小新在 i(1≤i≤n)號機器人工廠購買了一個機器人,這個機器人會從 i 號機器人工廠開始,順時針在馬路上行走,第一次行走會經過 i 號馬路,到達 i+1 號機器人工廠(如果 i=n,機器人會到達第 1 個機器人工廠),並將 i 號馬路上的所有金幣收集給小新。 遊戲中,環形馬路上不能同時存在 2 個或者 2 個以上的機器人,並且每個機器人最多能夠在環形馬路上行走 p 次。小新購買機器人的同時,需要給這個機器人設定行走次數,行走次數可以為 1~p 之間的任意整數。當馬路上的機器人行走完規定的次數之後會自動消失,小新必須立刻在任意一個機器人工廠中購買一個新的機器人,並給新的機器人設定新的行走次數。
以下是遊戲的一些補充說明:
-
遊戲從小新第一次購買機器人開始計時。
-
購買機器人和設定機器人的行走次數是瞬間完成的,不需要花費時間。
-
購買機器人和機器人行走是兩個獨立的過程,機器人行走時不能購買機器人,購買完機器人並且設定機器人行走次數之後機器人才能行走。
-
在同一個機器人工廠購買機器人的花費是相同的,但是在不同機器人工廠購買機器人的花費不一定相同。
- 購買機器人花費的金幣,在遊戲結束時再從小新收集的金幣中扣除,所以在遊戲過程中小新不用擔心因金幣不足,無法購買機器人而導致遊戲無法進行。也因為如此,遊戲結束後,收集的金幣數量可能為負。
現在已知每段馬路上每個單位時間內出現的金幣數量和在每個機器人工廠購買機器人需要的花費,請你告訴小新,經過 m 個單位時間後,扣除購買機器人的花費,小新最多能收集到多少金幣。
輸入輸出格式
輸入格式:
第一行 3 個正整數,n,m,p,意義如題目所述。
接下來的 n 行,每行有 m 個正整數,每兩個整數之間用一個空格隔開,其中第 i 行描
述了 i 號馬路上每個單位時間內出現的金幣數量(1≤金幣數量≤100),即第 i 行的第 j(1≤j≤m)個數表示第 j 個單位時間內 i 號馬路上出現的金幣數量。
最後一行,有 n 個整數,每兩個整數之間用一個空格隔開,其中第 i 個數表示在 i 號機器人工廠購買機器人需要花費的金幣數量(1≤金幣數量≤100)。
輸出格式:
共一行,包含 1 個整數,表示在 m 個單位時間內,扣除購買機器人
花費的金幣之後,小新最多能收集到多少金幣。
輸入輸出樣例
2 3 2 1 2 3 2 3 4 1 2
5
說明
【資料範圍】
對於 40%的資料,2≤n≤40,1≤m≤40。
對於 90%的資料,2≤n≤200,1≤m≤200。
對於 100%的資料,2≤n≤1000,1≤m≤1000,1≤p≤m。
NOIP 2009 普及組 第四題
一開始想到一個思路.
用dp[i][j][l]表示第i個時間點,在第j個地方,走了l步的最大收益,後來一看資料範圍發現肯定過不了。
我們用dp[i]表示在第i個時間點的最小花費,因為最後沒有詢問j和l,而且j和l我們可以通過暴力列舉出來,所以可以優化掉
對於每個時間的地點,因為購買機器人之後機器人最多可以走p步,所以我們可以從j向前列舉p個節點,
因為這道題有點類似於無向圖,所以這樣列舉是可行的
每次計算出在當前時間點的最小花費,
因為每走一步需要花費一個時間點,所以now每次加上i-k的時間的收益就好,
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const int MAXN=1001; 7 void read(int &n) 8 { 9 char c='+';int x=0;bool flag=0; 10 while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;} 11 while(c>='0'&&c<='9') 12 {x=x*10+c-48;c=getchar();} 13 flag==1?n=-x:n=x; 14 } 15 int dp[MAXN]; 16 // 第i個時間點,在第j個地方 17 int n;// 節點。 18 int m;//單位時間 19 int p;//行走次數 20 int mon[MAXN][MAXN]; 21 int spend[MAXN]; 22 int pre(int p) 23 { 24 if(p==1) 25 return n; 26 else return p-1; 27 } 28 int main() 29 { 30 read(n);read(m);read(p); 31 for(int i=1;i<=n;i++) 32 for(int j=1;j<=m;j++) 33 read(mon[i][j]); 34 for(int i=1;i<=n;i++) 35 read(spend[i]); 36 for(int i=1;i<=m;i++) 37 { 38 for(int j=1;j<=n;j++) 39 { 40 int r=pre(j),now=0; 41 now=mon[r][i];// 初始化 42 for(int k=1;k<=p;k++) 43 { 44 if(i-k<0)break; 45 dp[i]=max(dp[i],dp[i-k]-spend[r]+now); 46 r=pre(r); 47 now+=mon[r][i-k]; 48 } 49 } 50 } 51 printf("%d",dp[m]); 52 return 0; 53 }