content
- The concept of greed
- The nature of greed
- event scheduling issues
- boat problem
- Select Disjoint Intervals
- knapsack problem
The concept of greed
Greedy algorithm is an algorithm design technology for solving combinatorial optimization problems.
Unlike dynamic programming algorithms, greedy algorithms do not have to consider the selection results of all subproblems when making decisions.
The nature of greed
- greedy choice
- optimal substructure properties
Conditions of application of the greed law
The solution of the problem can be composed of a series of decision steps, and each step of the decision depends on a greedy strategy that is locally optimal. It is guaranteed that the choice of each step based on the properties of the local optimization will eventually lead to the global optimal solution.
main design steps
- View problem solving as a series of decisions;
- Determine the local optimization properties on which the decisions at each step are based;
- Prove that the choice of each step based on the properties of local optimization eventually leads to a global optimal solution.
The main difficulty of the greedy method is to prove its correctness . The correctness of the greedy method can be proved by mathematical induction.
event scheduling issues
topic link
problem solving code
#include <bits/stdc++.h>
const int maxn = 10000 + 10;
using namespace std;
struct Node{
int l,r;
};
int cmp(Node a,Node b){
return a.r < b.r;
}
int main(){
int T,n;
Node node[maxn];
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i = 0; i < n; i++)scanf("%d%d",&node[i].l,&node[i].r);
sort(node,node+n,cmp);
int End = node[0].r;
int sum = 1;
for(int i = 1; i < n; i++){
if(node[i].l > End){
sum++;
End = node[i].r;
}
}
printf("%d\n",sum);
}
return 0;
}
boat problem
Topic description
There are n people, and the weight of the ith person is wi. Each boat has a maximum carrying capacity of C and can only carry a maximum of two people. Load everyone with the fewest boats.
Parse
Start with the lightest person first, then he should sit with the heaviest person (greedy choice, save more space for the back), if everyone can't ride with it, then the only way is for everyone to do one ship.
Otherwise, he should choose the heaviest of the people who can ride with him in the boat so that it doesn't go to waste.
Two points of proof by contradiction:
- Assuming i is not in the same boat with anyone, putting j (or someone lighter than j) in the same boat will reduce the number of boats.
- Assuming that i and k are in the same ship, because j is the heaviest match with i, so w(k)<=w(j), then adding other ships to j may make other ships overweight, and the number of ships used will increase;
#include <bits/stdc++.h>
const int maxn = 100 + 10;
using namespace std;
int cmp(const void *a,const void *b){
return *(int*)a - *(int*)b;
}
int main(){
//freopen("in.txt","r",stdin);
int w[maxn],n,C;
while(scanf("%d%d",&C,&n) != EOF){
for(int i = 1; i <= n; i++)scanf("%d",&w[i]);
//sort(w+1,w+1+n); //排序
qsort(w,n+1,sizeof(w[1]),cmp); //数组,最后的下标加一,开始下标
int i = 1, j = n;
int ans = 0;
while( i <= j){
if( i == j){ ans++; break; } //当相等的时候也就意味着其他的配对了,只剩自己了
if(w[i] + w[j] <= C){ //如果可以配对
ans++;
i++;
j--;
}else{ //不能配对 -->只能重的人做一艘船
ans++;
j--;
}
}
printf("%d\n",ans);
}
return 0;
}
Test Data
测试数据:
85 6
5 84 85 80 84 83
90 3
90 45 60
100 5
50 50 90 40 60
输出:
5
3
3
Select Disjoint Intervals
topic
It is to give a series of intervals, find the most interval, and require the largest number of intervals. These intervals do not intersect. It should be noted that these intervals are closed intervals.
topic link
Problem solving ideas
It is also a greedy choice, sorted by the right endpoint of the interval.
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000 + 10;
struct Node{
int x,y;
bool operator < (const Node & rhs) const{
return y < rhs.y || (y == rhs.y && x < rhs.x);
}
}node[maxn];
int main(){
//freopen("in.txt","r",stdin);
int n,kase = 0;
int path[maxn]; //记录区间
while(scanf("%d",&n) != EOF){
for(int i = 0; i < n; i++){
scanf("%d%d",&node[i].x,&node[i].y);
if(node[i].x > node[i].y)swap(node[i].x,node[i].y); //注意这里要交换一下
}
sort(node,node+n);
int End = node[0].y; //先选择第一个
int sum = 1; //记录个数,第一个必须选
for(int i = 1; i < n; i++){
if(node[i].x > End){
path[sum++] = i;
End = node[i].y;
}
}
//printf("%d %d\n",node[0].x,node[0].y);
//for(int i = 1; i < sum; i++)printf("%d %d\n",node[path[i]].x,node[path[i]].y); //输出区间
printf("Case %d:\n",++kase);
printf("%d.\n",sum);
}
return 0;
}
knapsack problem
The knapsack problem is different from the 01 knapsack problem. The difference is that each item can be put into a part. In this case, we greedily choose the items whose unit weight value is from the highest to the bottom, and the last item can be loaded with as much as possible. The
01 knapsack problem uses greed The reason why the algorithm can not get the optimal solution is that the backpack cannot be guaranteed to be full, and some of the idle backpack space reduces the value of each kilogram of backpack space .
#include <bits/stdc++.h>
const int maxn = 100 + 10;
using namespace std;
double x[maxn];
struct Kanpsack{
int w,v;
bool operator < (const Kanpsack& rhs){
return v*1.0/w > rhs.v*1.0/rhs.w;
}
};
int main(){
//freopen("in.txt","r",stdin);
int n,C;
scanf("%d %d",&n,&C);
Kanpsack kp[maxn];
for(int i = 0; i < n; i++)scanf("%d %d",&kp[i].w,&kp[i].v);
sort(kp,kp+n);
for(int i = 0; i < n; i++)x[i] = 0;
int now = C,i;
for(i = 0; i < n; i++){
if(kp[i].w > now)break;
x[i] = 1;
now -= kp[i].w;
}
if(i <= n-1)x[i] = now*1.0/kp[i].w; //把最后一个能装多少装多少
for(int i = 0; i < n; i++)printf("%lf ",x[i]);
printf("\n");
return 0;
}
Test Data
3 50
10 60
20 100
30 120
output
1.000000 1.000000 0.666667