1. 程式人生 > 遊戲攻略 >《原神攻略》全鳴草收集位置一覽

《原神攻略》全鳴草收集位置一覽

# 貪心演算法總結

## 貪心演算法簡述

貪心演算法是原理最簡單的一種演算法,甚至可以將其中一些部分理解為常識或者是常規思維。

他採取貪心的策略,即保證每次操作都是最優的,先得到區域性的最優解,從而使最終的結果是最優的。

## leetcode刷題

### 分配問題

### 455.Assign Cookies(Easy)

##### 題目描述:

有一群孩子和一堆餅乾,每個孩子都有一個飢餓度,每個餅乾都有一個大小。每個孩子只能吃最多一個餅乾,且只有餅乾的大小大於孩子的飢餓度時,這個孩子才可以吃飽。求解最多有多少個孩子可以吃飽。

##### 輸入輸出樣例:

---

Input : [1,2],[1,2,3]

Output : 2

---

##### 一些想法:

這裡的貪心策略就是儘可能的將剩餘孩子中飢餓度最小的滿足,每一次只考慮最小的飢餓度。

所以演算法實現就是先將所有孩子的飢餓度和餅乾的大小從大到小進行排序,然後設定兩個指標分別指向child和cookie,當遇到cookie的值大於等於孩子的飢餓度時,即滿足條件,故將指標均後移即可。若不滿足,cookie後移即可。當有一個到達盡頭時,迴圈結束。返回已經滿足的孩子數量。

##### 程式碼部分:

```c++
int findContentChildren(vector& children,vector& cookies) {
int child = 0 ;
int cookie = 0 ;
while(child<children.size() && cookie<cookies.size()){
if(children[child] <= cookies[cookie]){
child++ ;
cookie++ ;
}
else
cookie++ ;
}
return child ;
}
```

### 135.Candy(Hard)

##### 題目描述:

老師想給孩子們分發糖果,有 N 個孩子站成了一條直線,老師會根據每個孩子的表現,預先給他們評分。

你需要按照以下要求,幫助老師給這些孩子分發糖果:

每個孩子至少分配到 1 個糖果。

評分更高的孩子必須比他兩側的鄰位孩子獲得更多的糖果。

那麼這樣下來,老師至少需要準備多少顆糖果呢?

##### 輸入輸出樣例:

---

Input : [1,0,2]

Output : 5

---

---

Input : [1,2,2]

Output : 4

---

##### 一些想法:

一開始為了有一個基準值,方便比較,同時題目要求所有孩子都至少有一個糖果,所以先應該將所有孩子的糖果全部初始化為1.

可以分成兩邊進行考慮,進行兩輪的遍歷。如果遇到自己比鄰位大的話,就在鄰位的基礎上加一即可。

最後將所有值相加並返回即可。

##### 程式碼部分:

```c++
int candy(vector& ratings){
int size = ratings.size() ;
if(size <= 1)
return size ;
vector candies(,1) ; //將所有的糖果數全部初始化為1
//第一輪,從左往右進行比對
for(int i = 1 ;i < size ; i++){
if(ratings[i] > ratings[i-1]){
candies[i] = candies[i-1]+1 ;
}
}
//第二輪,從右向左進行比對
for(int i = size-1 ; i > 0; i--){
if(ratings[i-1] > ratings[i]){
candies[i-1] = max(candies[i-1],ratings[i]+1) ;
}
}
//最終返回所有值的和
return accumulate(candies.begin(),candies.end(),0) ;
}


```

### 區間問題

### 435.Non-overlapping Intervals(Medium)

##### 題目描述:

給定一個區間的集合,找到需要移除區間的最小數量,使剩餘區間互不重疊。

##### 輸入輸出樣例:

##### 一些想法:

選取的貪心策略是先對於所有區間的尾節點,進行升序排序,然後以保留尾節點最小而且與前一個結點無重疊區間為優先。

排序的時候會用到c++的lamda表示式,可以利用其與sort結合進行自定義排序。

##### 程式碼部分:

```c++
int eraseOverlapIntervals(vector<vector>& intervals){
int sum = 0 ; //肯定要先設定一個計數器
//進行按照尾節點的升序排序
sort(intervals.begin(),intervals.end(),[](vector a,vector b){
return a[1]>b[1] ;
}) ;
int pre = intervals[0][1] ;
for(int i = 1 ; i < intervals.size() ; i++){
if(intervals[i][0] < pre){
sum++ ;
}
else{
pre = intervals[i][1] ;
}
}
return sum ;
}
```

### 605.Can Place Flowers(Easy)

##### 題目描述:

假設有一個很長的花壇,一部分地塊種植了花,另一部分卻沒有。可是,花不能種植在相鄰的地塊上,它們會爭奪水源,兩者都會死去。

給你一個整數陣列 flowerbed 表示花壇,由若干 0 和 1 組成,其中 0 表示沒種植花,1 表示種植了花。另有一個數 n ,能否在不打破種

植規則的情況下種入 n 朵花?能則返回 true ,不能則返回 false。

##### 輸入輸出樣例:

![image-20210730171909324](C:\Users\86183\AppData\Roaming\Typora\typora-user-images\image-20210730171909324.png)

![image-20210730172035150](C:\Users\86183\AppData\Roaming\Typora\typora-user-images\image-20210730172035150.png)

##### 一些想法:

(本人比較拙劣的方法,本人是初級學leetcode,以後如果自己想或者發現了有更好的題解也會進一步更新的)

##### 程式碼部分:

```c++
bool canPlaceFlowers(vector& flowerbed, int n) {
int m = flowerbed.size() ;
int sum = 0 ;
if(m == 1 && flowerbed[0] == 0){
sum++ ;
}
else{
for(int i = 0;i<m;i++){
if(flowerbed[i] == 0){
if(i == 0){
if(flowerbed[i+1] == 0){
flowerbed[i] = 1 ;
sum++ ;
}
}
else if(i == m-1){
if(flowerbed[i-1] == 0){
flowerbed[i] = 1 ;
sum++ ;
}
}
else {
if(flowerbed[i-1] == 0 && flowerbed[i+1] == 0){
flowerbed[i] = 1 ;
sum++ ;
}
}
}
}
}
if(sum>=n)
return true ;
else
return false ;
}
```

未完待續......