Greedy Algorithm Summary--Example Problems (Activity Arrangement Problem, Boating Problem, Selecting Disjoint Intervals, Knapsack Problem)

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
    write picture description here
    write picture description here

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

    event scheduling issues

    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

    Guess you like

    Origin http://43.154.161.224:23101/article/api/json?id=324781328&siteId=291194637