P1070 道路遊戲(單調佇列 動態規劃)

2021-08-21 20:47:17 字數 2120 閱讀 3688

題幹在這裡:

這道題分了三類,

對於 40%的資料, 2≤n≤40,1≤m≤40

對於 90%的資料,2≤n≤200,1≤m≤200

對於 100%的資料2≤n≤1000,1≤m≤1000,1≤p≤m

先說狀態轉移方程:f[i][j]表示在i時刻在j工廠買了乙個機械人

f[i][j]=max(其中sum表示從第i時刻開始,機械人從第j個工廠開始收集金幣,經過k步所能收集的金幣數,money表示從j工廠買機械人需要的金幣數,0<=y<=n-1)

如果不採用任何優化的話,只能得40%的分,我們先採取第一步優化:在狀態轉移的過程中,我們列舉了i,j,k,y。資料範圍是200的時候就爆了。其實我們完全可以不需要列舉y。我們可以用opt陣列來儲存第i行f[i][j]的最大值,要用的時候直接呼叫就行了(不需要再列舉一遍j)。

程式如下:

#include

#include

using

namespace

std;

const

int maxans=100*1000+10;

int n,m,p,a[1100][1100],f[1100][1100],need[1100],opt[1100];

int add(int fac,int step,int tim)

void prepare()

opt[i]=max(opt[i],f[i][j]);}}

}void readin()

}for(int i=0;icin>>need[i];

}int main()

}for(int i=0;i<=1010;++i)

opt[i]=-maxans;

prepare();

cout

<0]

0;}

當資料範圍是200的時候,在一秒內計算200^3完全可以。但是如果是1000的範圍內的話,就會超時,所以我們要請出最後的王牌——

首先,讓我們了解一下神馬是單調佇列:

但是——這道題不是直線上的單調佇列,而是斜線上的。

s[i][j]表示i,j所在的這一條斜線到第一行的和,遞推關係式為:

s[i+1][(j+1)%n]=s[i][j]+a[i+1][(j+1)%n];

其中,所有(j-i+n)%n得到的數相同的都為一條斜線

opt[i+k]和s[i][j]都和j有關,所以我們可以將二者的和儲存在queue陣列中,在求f[i][j]的時候再呼叫。

先將所有的s陣列求出來,以便呼叫,狀態轉移方程如上~;

有了s陣列,先將opt陣列附乙個很小的值(但是要注意opt[m]=0)之後我們就可以求queue(了!opt[i]在求完f[i][j]的時候再更新,轉移方程為:opt[i]=max(opt[i],f[i][j]))

其中,head表示投指標。tail表示尾指標,當且僅當

tail[k]>=head[k]&&x>=queue[k][tail[k]][1]時才需要做,因為是求最大值,這個數列是乙個單調遞減的數列如果後面加進來的數大於queue陣列尾的數,這個陣列尾的數就沒有用了,tail–,同理,如果這個陣列頭太遙遠,超過了可執行步數,head++;

最後獻上**~~~

#include

using

namespace

std;

const

int maxans=100*1000+10;

int n,m,p,a[1100][1100],f[1100][1100],need[1100],opt[1100];

int s[1100][1100],queue[1100][1100][2],head[1100],tail[1100];

void readin()

}for(int i=0;icin>>need[i];

for(int i=0;i0][i]=a[0][i];

for(int i=0;i<=m-1;i++)

}}void work()

}}int main()

其實寫完這篇部落格,我個人是濛濛懵逼的。。。

P1070 道路遊戲

小新正在玩乙個簡單的電腦遊戲。遊戲中有一條環形馬路,馬路上有 n 個機械人工廠,兩個相鄰機械人工廠之間由一小段馬路連線。小新以某個機械人工廠為起點,按順時針順序依次將這 n 個機械人工廠編號為1 n,因為馬路是環形的,所以第 n 個機械人工廠和第 1 個機械人工廠是由一段馬路連線在一起的。小新將連線...

洛谷P1070 道路遊戲

小新正在玩乙個簡單的電腦遊戲。遊戲中有一條環形馬路,馬路上有 n 個機械人工廠,兩個相鄰機械人工廠之間由一小段馬路連線。小新以某個機械人工廠為起點,按順時針順序依次將這 n 個機械人工廠編號為1 n,因為馬路是環形的,所以第 n 個機械人工廠和第 1 個機械人工廠是由一段馬路連線在一起的。小新將連線...

題解 洛谷P1070 道路遊戲(線性DP)

次元傳送門 洛谷p1070 一開始以為要用什麼玄學優化 沒想到o3就可以過了 我們只需要設f i 為到時間i時的最多金幣 需要倒著推回去 即當前值可以從某個點來 那麼狀態轉移方程為 f i max f i f i k val cost now now表示從now這個工廠來 cost表示在now買下了...