hdu1500 排序 單調佇列優化 )

2022-08-24 20:48:09 字數 1368 閱讀 4187

從n根筷子裡面, 選擇k+8個集合的筷子,每個集合三根筷子, a<=b<=c, 費用是(a-b)^2,

問最小的費用是多少。

將n根筷子排序之後,可以知道a和b的下標一定是連續的。

比如有 a b c d ,  那麼不可能是a c 乙個集合, b d乙個集合, 因為這樣費用反而更大。

設dp[i][j] 為第i個集合的筷子,以j結尾,  就是說 a和b分別是第j和第j-1個筷子

dp[i][j] = min(dp[i-1][k]) + (a[j]-a[j-1])^2

那麼如何處理第三根筷子呢?

只要將筷子從大到小排序。

dp[i][j] 的j是從3*i開始的,

而dp[i-1][k]的k是從(i-1)*3開始的,這樣就保證了每個集合在前面的筷子中,都有一根筷子與自己配對。

dp[i][j] = min(dp[i-1][k]) + (a[j]-a[j-1])^2  這個迴圈可以用單調遞增佇列來優化,保證隊頭最小就行了。

#pragma warning(disable:4996)

#pragma comment(linker, "/stack:1024000000,1024000000")#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

typedef __int64 ll;

const

int inf = 999999999;/*

a b 絕逼是連續的,問題是c怎麼怎麼描述

dp[i][j] 第i套筷子是由j結束

dp[i][j] = min(dp[i][j],dp[i-1][k])

*/const

int n = 5000 + 10

;int

a[n];

int dp[1111

][n];

intq[n], head, tail;

intmain()

for (int j = 3 * i; j <= n;++j)

}int ans =inf;

for (int j = 3 * k;j <= n;++j)

ans =std::min(ans, dp[k][j]);

printf(

"%d\n

", ans);

}return0;

}

HDU 1106 排序(排序)

輸入一行數字,如果我們把這行數字中的 5 都看成空格,那麼就得到一行用空格分割的若干非負整數 可能有些整數以 0 開頭,這些頭部的 0 應該被忽略掉,除非這個整數就是由若干個 0 組成的,這時這個整數就是0 你的任務是 對這些分割得到的整數,依從小到大的順序排序輸出。input輸入包含多組測試用例,...

hdu 4374 dp 單調佇列優化

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

hdu 3530 dp 單調佇列優化

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