hdu 4362 單調佇列優化dp

2021-07-11 11:31:31 字數 2405 閱讀 6277

題意:有m個階段,每個階段都有n個龍珠,當在某一階段選擇乙個龍珠,該階段其他龍珠都會消失。給出兩個m*n的矩陣,第乙個矩陣表示消滅第i個階段第j個龍珠的位置,第二個矩陣表示取第i個階段第j個龍珠消耗的能量,同時當第x個位置到第個位置需要消耗 | y - x|的能量。問最後每個階段取走乙個龍珠最小的能量消耗。

解題思路:dp[i][j]表示第i個階段選擇第j個龍珠的最小耗能。

轉移方程:dp[i][j] = min,這裡需要列舉的是i,j,k所以時間複雜度o(m*n*n),這題資料好像卡得不是很緊,所以運氣好點是可以ac的。不過不是正解。

這裡可以利用單調佇列。因為dp[i][j]=min  (loc[i][j] > loc[i-1][k]),所以可以只需要維護dp[i-1][k] - loc[i-1][k]即可。由於有絕對值,所以我這裡用了兩個單調佇列,乙個維護dp[i-1][k] - loc[i-1][k],另乙個維護dp[i-1][k] + loc[i-1][k],但不知道什麼原因wa了。。。

先放在這裡,等以後有思路了再改吧。。也希望路過我部落格的哪位大神指點指點。

#include#include#include#includeusing namespace std;

const int maxn = 1005;

const int inf = 0x3f3f3f3f;

struct node

mat[55][maxn];

int n,m,x;

int dp[55][maxn],q1[maxn],q2[maxn],h1,h2,t1,t2;

bool cmp(node a,node b)

int main()

for(int i = 1; i <= n; i++)

dp[1][i] = abs(x - mat[1][i].pos) + mat[1][i].cost;

for(int i = 2; i <= m; i++)

for(int j = 1; j <= n; j++)

}int ans = inf;

for(int i = 1; i <= n; i++)

ans = min(ans,dp[m][i]);

printf("%d\n",ans);

} return 0;

}

ps: 仔細想了想,確實自己的單調佇列有問題,因為我是先把所有的dp[i-1]層的送入佇列,就會出現問題,在我後面的迴圈列舉dp[i]層的時候一些有效位置可能不在佇列裡。所以參考了別人的**,還是要先列舉dp[i][j]中的j,保證我先選擇第j個位置,由於已經是有序的了,所以就直接找不大於mat[i][j].pos位置的最小值即可,同理,由於有絕對值,所以還要反著迴圈一次。

詳細的過程看**:

#include#include#include#includeusing namespace std;

const int maxn = 1005;

const int inf = 0x3f3f3f3f;

struct node

mat[55][maxn];

int n,m,x;

int dp[55][maxn],q1[maxn],q2[maxn],h1,h2,t1,t2;

bool cmp(node a,node b)

int main()

for(int i = 1; i <= n; i++)

dp[1][i] = abs(x - mat[1][i].pos) + mat[1][i].cost;

for(int i = 2; i <= m; i++)

dp[i][j] = min + mat[i][j].pos + mat[i][j].cost;

}k = n, min = inf;

for(int j = n; j >= 1; j--)

dp[i][j] = min(dp[i][j],min - mat[i][j].pos + mat[i][j].cost);

}} int ans = inf;

for(int i = 1; i <= n; i++)

ans = min(ans,dp[m][i]);

printf("%d\n",ans);

} return 0;

}

hdu 4374 dp 單調佇列優化

解法 dp 單調佇列!有乙個的樓房,從第一層某個位置出發上樓,每次能爬上一層樓也可以在同一層左右移動,但是在每一層的移動距離不能超過某個值。現在每個位置都有乙個數值,求從第一層出發到最後一層經過的路徑上最多能取到的最大價值。dp i j 表示 第i行,第j個數字的最大價值!sum i j 表示 第i...

hdu 3530 dp 單調佇列優化

題目 題意 給你乙個長度為n的數列,要求乙個子區間,使得區間的最大值與最小值的差s滿足,m s k,求滿足條件的最長子區間 分析 做了前面幾題後,這題容易想到用兩個單調佇列維護當前最值,作為判斷條件,如果差值大於k了,就去掉較前面的那個佇列元素,並把區間頭更新為它的標號 1,這裡注意差值小於m並不需...

hdu 3514 dp 單調佇列優化

題目 題意 給你乙個環形的數列,問你連續長度為k的數的和的最大值,並且輸出區間座標,使座標字典序最小 分析 把環形轉換成直線處理即可,求出累加和陣列,用優先佇列維護 include include include includeusing namespace std const int maxn 2...