從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並不需...