CF998B Cutting 題解 DP 貪心

2022-05-19 22:07:27 字數 2528 閱讀 8866

題目描述

有很多東西是可以被切割的,比如——樹、紙張或者繩子。在這道題目裡面你需要切割乙個整數序列。

現在告訴你乙個整數序列,在這個整數序列裡面有一些數,它們可能是奇數,也可能是偶數。

給你乙個固定的預算(因為切割是有成本的),你需要盡可能多地將這個整數序列切分成一系列連續子串行,

使得每乙個連續子串行中的 奇數元素的個數 和 偶數元素的個數 相同。

比如,給你乙個整數序列 [4,1,2,3,4,5,4,4,5,5] ,你可以將其切割兩次變成

[4,1 | 2,3,4,5 | 4,4,5,5] 。其中,[4,1] 、 [2,3,4,5] 以及 [4,4,5,5] 這三個連續子串行中包含的奇數個數等於偶數個數。

如果你要將第 i 個元素和第 i+1 個元素之間切一刀,我們假設第 i 個元素對應的數值為 x ,第 j 個元素對應的數值為 y ,那麼你需要消耗 |x-y| 個位元幣。

(|x-y| 表示 x-y 的差的絕對值)。

而你的預算只有 b 個位元幣,所以你需要計算一下在最多消耗 b 個位元幣的情況下,你最多可以切幾次。

輸入格式

輸入的第一行包含兩個整數 n (2<=n<=100)和 b(1<=b<=100),分別表示整數序列中元素的個數和你最多可用的位元幣的數量。

輸入的第二行包含 n 個整數,用於表示整數序列中的元素:a1,a2,……,an(1<=ai<=100)。

輸出格式

輸出乙個整數,用於表示在最多消耗 b 個位元幣的情況下,你最多可以切幾刀,使得每乙個切出來的連續子串行中包含相同的奇偶元素。

樣例輸入1

6 4

1 2 5 10 15 20

樣例輸出1
1
樣例輸入2
4 10

1 3 2 4

樣例輸出2
0
樣例輸入3
6 100

1 2 3 4 5 6

樣例輸出3
2
樣例解釋

對於樣例1,我們可以在 2 和 5 之間切割一刀,消耗 3 個位元幣;

對於樣例2,我們無法切割;

對於樣例3,我們可以在 2 和 3 之間 以及 4 和 5 之間切割一刀,消耗 1+1=2 個位元幣。

這道題目涉及的演算法是「dp」+「貪心」,可以用 dp+sort 或者 dp+heap 來做。

首先我們假設 n 個元素的座標從 1 到 n ,他們分別對應 a[1] 到 a[n] 。

然後我們開乙個輸出 cc ,cc[i] 用於表示從 a[1] 到 a[i] 這 i 個數中奇數個數減去偶數個數之差。

那麼對於 1 到 n-1 範圍內的 i ,如果 cc[i] == 0 ,那麼它這個位置就是可以切割的,切割的成本是 abs(a[i+1]-a[i]) 。

dp+sort解法:

我們將 1 到 n-1 範圍內的所有滿足 cc[i]==0 條件的 i 對應的 abs(a[i+1]-a[i]) 放入乙個陣列中,然後將這個陣列從小到大排序,每次取出乙個數計數器cnt++,同時b減去這個數,直到b不夠用為止;

dp+heap(堆)解法:

我們首先構造乙個最小堆(可以用 priority_queue 模擬),然後將 1 到 n-1 範圍內的所有滿足 cc[i]==0 條件的 i 對應的 abs(a[i+1]-a[i]) 放入最小堆中1,然後每次從最小堆中取出堆頂元素,計數器cnt++,同時b減去這個數,直到b不夠用為止。

1、下面的**演示了 dp+sort 的操作:

#include using namespace std;

const int maxn = 110;

int n, b, cnt, a[maxn], cc[maxn];

vectorvec;

int main()

for (int i = 1; i < n; i ++) if (!cc[i]) vec.push_back(abs(a[i+1]-a[i]));

sort(vec.begin(), vec.end());

for (vector::iterator it = vec.begin(); it != vec.end(); it ++)

cout << cnt << endl;

return 0;

}

2、下面的**演示了 dp+heap 的操作:

#include using namespace std;

const int maxn = 110;

int n, b, cnt, a[maxn], cc[maxn];

priority_queue, greater> que;

int main()

for (int i = 1; i < n; i ++) if (!cc[i]) que.push(abs(a[i+1]-a[i]));

while (!que.empty())

cout << cnt << endl;

return 0;

}

題解 CF1119H Tripe題解

題目傳送門 給出 n,t,x,y,z 值域 le 2 t 給出 n 個三元組 a i,b i,c i 表示有 x 個 a i y 個 b i z 個 c i 對於每個 k in 0,2 t 1 求出從每組選出乙個數的異或值為 k 的方案數。先定義 delta n f delta 表示多項式 f 的第...

題解 CF1485 簡要題解

奇怪的難度。當 b 2 的時候再操作,操作次數是一定的。因此 b 的變化量很小,暴力列舉。考慮哪個數不同,然後不同後可以選擇的區間是什麼。會發現中間夾著的區間選兩遍,旁邊的選一遍。做字首和好了。簡單轉化發現一定要滿足 a k b 1 k。列舉 b 貢獻式帶有乙個 min 找到其分割點,前一部分直接求...

CF1178比賽題解

a題 小學抽屜問題,答案就是 max n s,n t 1 複雜度 o t include int t,n,m,i,j,k int a 2 int main b題 我們維護乙個 vector 陣列 v 其中 v i 存的是字母 i 所出現的位置。那麼因為我們是依次 text 的,那麼第 i 個字母的位...