演算法筆記之演算法初步(貪心)
阿新 • • 發佈:2018-12-20
貪心演算法是以區域性最優解,而達到整體的最優解。貪心演算法的證明往往要比貪心解法本身要更難,所以在無法舉出反例的情況下要勇於使用。
1.簡單貪心
思路:將月餅按單價的高低排序,從單價高的月餅向單價低的遍歷,優先選擇單價高的月餅,其中每一步都是選擇當前最優的選擇來達到最後的結果。
注意要點:
- 遍歷每一個,要區分需求量與庫存量的大小,區別對待
- 最後結果要用double輸出,月餅庫存量和總售價也要用double來表示,不然容易出問題。
#include<iostream> #include<algorithm> using namespace std; const double ep = 1e-8; const int N = 1010; struct moonCake{ double quntity; //總量 double sell;// 總價錢 double price;// 單價 }moonCakes[N];// 注意這裡為什麼要用double, price為double bool cmp(moonCake c1, moonCake c2){//排序函式 return c1.price > c2.price; } int main(){ int n; double need; scanf("%d%lf", &n, &need); for(int i = 0; i < n; ++i){ scanf("%lf", &moonCakes[i].quntity); } for(int i = 0; i < n; ++i){ scanf("%lf", &moonCakes[i].sell); moonCakes[i].price = (1.0) * moonCakes[i].sell / moonCakes[i].quntity; } sort(moonCakes, moonCakes + n, cmp);// 從大到小排序 double money = 0.0, price = 0.0;//money為最後的結果 for(int i = 0; i < n; ++i){ if(need){ //當需求大於庫存量時 if( need >= moonCakes[i].quntity){ money += moonCakes[i].sell; need -= moonCakes[i].quntity; } //當需求小於庫存量時 else{ money += moonCakes[i].price * need; need = 0; } } else break;//當需求為0 } printf("%.2f", money); return 0; }
注意:第一個數一定要非零
#include<iostream> #include<stdio.h> using namespace std; int number[10] = {0}; int count = 0; int main(){ for(int i = 0; i < 10; ++i){ scanf("%d", &number[i]); count += number[i]; } int k = 1; while(number[k] == 0){// 為第一位,輸出非零數 k++; } printf("%d", k); number[k]--; count--; k = 0; while(count){// 依次輸出每個數 while(number[k] == 0){ k++; } printf("%d", k); number[k]--; count--; } return 0; }
2.區間貪心
給出N個開區間(x, y) ,從中選擇儘可能多的空間,使這些空間兩兩沒有交集。例如(1,3),(2,4),(3,5),(6,7),可以看到最多選擇三個,(1,3),(3,5),(6,7)。大體的思路是如果一個區間被另一個區間所包圍,那麼就選擇那個小的區間,能留出更多的空間給其他的區間。推廣開來,可以固定從尾端開始,將其按照X從小到大的值來排序,每次在選擇範圍內選X值大的區間(從後往前開始選擇,X值大的代表其區間為相對小的區間,如果是從前往後開始選擇,Y的值正好相反)
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXL = 110;
struct interval{
int x;
int y;
}intervals[MAXL];
bool cmp(interval v1, interval v2){// 按照X的值從小到大排序
if(v2.x != v1.x) return v1.x < v2.x;
else return v1.y > v2.y;// 如果X值相等,則Y大的排在前面
}
int main(){
int N;
scanf("%d", &N);
for(int i = 0; i < N; ++i){
scanf("%d%d", &intervals[i].x, &intervals[i].y);
}
sort(intervals, intervals + N, cmp);// 排序
int x, y, count = 0;
if(N){// 如果N存在,從後往前選擇最後一個區間
count = 1;
x = intervals[N - 1].x;
}
for(int i = N - 2; i >= 0; --i){
y = intervals[i].y;
if( y <= x){// 開區間不能重合
x = intervals[i].x;
count++;
}
}
printf("%d", count);
return 0;
}