zoukankan      html  css  js  c++  java
  • 【算法总结】贪心法

    一、

      贪心法就是遵循某种规则,不断贪心地选取当前最优策略的算法设计方法。

    二、

    1.硬币问题

      有1元、5元、10元、50元、100元、500元的硬币各$C_{1}$、$C_{5}$、$C_{10}$、$C_{50}$、$C_{100}$ 、$C_{500}$ 枚。现在要用这些硬币来支付$A$元,最少需要多少枚硬币?假定本题至少存在一种支付方案。 

      最少硬币,直觉告诉我们先尽可能多地用大面值硬币,然后再用较小的硬币,依次取硬币直至完成支付。即优先使用面值大的硬币。此题也可看作背包问题。不过贪心算法更简单高效。

     1 const int V[6]={1, 5, 10, 50, 100, 500};
     2 int C[6];
     3 int A;
     4 void solve() {
     5     int ans = 0;
     6     for (int i = 5; i >= 0; --i) {
     7         int t = min(A / V[i], C[i]); // 使用硬币 i 的枚数
     8         A -= t * V[i];
     9         ans += t;
    10     }
    11 
    12     printf("%d
    ", ans);
    13 }

    2.区间问题

    区间调度问题

       有n项工作,每项工作分别在$s_{i}$时间开始,在$t_{i}$时间结束。对于每项工作,你都可以选择参与与否。如果选择了参与,那么自始至终都必须全程参与。此外,参与工作的时间段不能重叠(即使是开始的瞬间和结束的瞬间的重叠也是不允许的)。你的目标是参与尽可能多的工作,那么最多能参与多少项工作呢?

      感觉有点偏向于智力题,不妨设想能想到的可能性

    • 选取开始时间最早的工作
    • 选取结束时间最早的工作
    • 选取用时最短的工作
    • 选取与最少可选工作有重叠的工作

      一个个举反例,可知1、3、4都存在反例。

     1 const int MAX = 100005;
     2 int N, s[MAX], t[MAX];
     3 
     4 pair<int, int> itv[MAX];
     5 
     6 void solve() {
     7     for (int i = 0; i < N; ++i) {
     8         itv.first = t[i];
     9         itv.second = s[i];
    10     }
    11     sort(itv, itv + N);
    12 
    13     int cnt = 0, t = 0;
    14     for (int i = 0; i < N; ++i) {
    15         if (t < itv[i].second) {
    16             ++cnt;
    17             t = itv[i].first;
    18         }
    19     }
    20     printf("%d
    ", cnt);
    21 }

    3.字典序最小问题

    POJ 3617 Best Cow Line

    Description
    
    FJ is about to take his N (1 ≤ N ≤ 2,000) cows to the annual"Farmer of the Year" competition. In this contest every farmer arranges his cows in a line and herds them past the judges.
    
    The contest organizers adopted a new registration scheme this year: simply register the initial letter of every cow in the order they will appear (i.e., If FJ takes Bessie, Sylvia, and Dora in that order he just registers BSD). After the registration phase ends, every group is judged in increasing lexicographic order according to the string of the initials of the cows' names.
    
    FJ is very busy this year and has to hurry back to his farm, so he wants to be judged as early as possible. He decides to rearrange his cows, who have already lined up, before registering them.
    
    FJ marks a location for a new line of the competing cows. He then proceeds to marshal the cows from the old line to the new one by repeatedly sending either the first or last cow in the (remainder of the) original line to the end of the new line. When he's finished, FJ takes his cows for registration in this new order.
    
    Given the initial order of his cows, determine the least lexicographic string of initials he can make this way.
    
    Input
    
    * Line 1: A single integer: N
    * Lines 2..N+1: Line i+1 contains a single initial ('A'..'Z') of the cow in the ith position in the original line
    
    Output
    
    The least lexicographic string he can make. Every line (except perhaps the last one) contains the initials of 80 cows ('A'..'Z') in the new line.
    
    Sample Input
    
    6
    A
    C
    D
    B
    C
    B
    Sample Output
    
    ABCBCD
    View Code

      看起来挺简单的,只要比较S的头部和尾部的字符大小即可,但是有个问题,如果相等该取哪一个?假如S是CCABCC,取头部,如果S是CCDBCC,则是取尾部。

      按照字典序比较S和将S反转后的字符串S'。如果S较小,取S的头部,如果S'较小,则取S的尾部。

      字典序是指从前到后比较两个字符串大小的方法。如果不同则第1个字符较小的字符串更小,如果相同则继续比较第2个字符。。。如此继续,来比较整个字符串的大小。

     1 #include <iostream>
     2 #include <vector>
     3 #include <limits.h>
     4 #include <algorithm>
     5 #include <math.h>
     6 #include <queue>  
     7 using namespace std;
     8 
     9 const int MAX = 2000 + 5;
    10 const int INF = 0x3f3f3f3f; // 常用用法,防止溢出
    11 
    12 char s[MAX];
    13 int N;
    14 
    15 int main(){
    16     scanf("%d", &N);
    17     for (int i = 0; i < N; ++i){
    18         scanf(" %c", &s[i]);
    19     }
    20     int a = 0, b = N - 1;
    21     int len = 0;
    22     while (a <= b) {
    23         bool left = false;
    24         for (int i = 0; a + 2 * i <= b; ++i) { // 反转字符串比较
    25             if (s[a + i] < s[b - i]) {
    26                 left = true;
    27                 break;
    28             }
    29             else if (s[a + i] > s[b - i]) {
    30                 left = false;
    31                 break;
    32             }
    33         }
    34         if (left)
    35             putchar(s[a++]);
    36         else
    37             putchar(s[b--]);
    38         ++len;
    39         if (len == 80) {
    40             printf("
    ");
    41             len = 0;
    42         }
    43     }
    44     printf("
    ");
    45 
    46     return 0;
    47 }
    View Code

    POJ 3069 Saruman's Army

    Description
    
    Saruman the White must lead his army along a straight path from Isengard to Helm’s Deep. To keep track of his forces, Saruman distributes seeing stones, known as palantirs, among the troops. Each palantir has a maximum effective range of R units, and must be carried by some troop in the army (i.e., palantirs are not allowed to “free floatin mid-air). Help Saruman take control of Middle Earth by determining the minimum number of palantirs needed for Saruman to ensure that each of his minions is within R units of some palantir.
    
    Input
    
    The input test file will contain multiple cases. Each test case begins with a single line containing an integer R, the maximum effective range of all palantirs (where 0 ≤ R ≤ 1000), and an integer n, the number of troops in Saruman’s army (where 1 ≤ n ≤ 1000). The next line contains n integers, indicating the positions x1, …, xn of each troop (where 0 ≤ xi ≤ 1000). The end-of-file is marked by a test case with R = n = −1.
    
    Output
    
    For each test case, print a single integer indicating the minimum number of palantirs needed.
    
    Sample Input
    
    0 3
    10 20 20
    10 7
    70 30 1 7 15 20 50
    -1 -1
    Sample Output
    
    2
    4
    Hint
    
    In the first test case, Saruman may place a palantir at positions 10 and 20. Here, note that a single palantir with range 0 can cover both of the troops at position 20.
    
    In the second test case, Saruman can place palantirs at position 7 (covering troops at 1, 7, and 15), position 20 (covering positions 20 and 30), position 50, and position 70. Here, note that palantirs must be distributed among troops and are not allowed to “free float.” Thus, Saruman cannot place a palantir at position 60 to cover the troops at positions 50 and 70
    View Code

      从第一个结点开始,找距离其R以内的最远的点,然后再以向右辐射R,找到该区间的右端点。以此类推。

     1 #include <iostream>
     2 #include <vector>
     3 #include <limits.h>
     4 #include <algorithm>
     5 #include <math.h>
     6 #include <queue>  
     7 using namespace std;
     8 
     9 const int MAX = 1000 + 5;
    10 const int INF = 0x3f3f3f3f; // 常用用法,防止溢出
    11 
    12 int a[MAX];
    13 int R, N;
    14 
    15 int main(){
    16     while (scanf("%d%d", &R, &N) != EOF && !(R == -1 && N == -1)) {
    17         for (int i = 0; i < N; ++i) {
    18             scanf("%d", &a[i]);
    19         }
    20         int cnt = 0;
    21         sort(a, a + N);
    22         for (int i = 0; i < N;) {
    23             int s = a[i++]; // 左端点
    24             while (i < N && s + R >= a[i])
    25                 ++i;
    26             int t = a[i - 1]; // 右端点
    27             while (i < N && t + R >= a[i])
    28                 ++i;
    29             ++cnt;
    30         }
    31         printf("%d
    ", cnt);
    32     }
    33 
    34     return 0;
    35 }
    View Code

    POJ 3253 Fence Repair

    Description
    
    Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into the N planks (i.e., whose length is the sum of the lengths Li). FJ is ignoring the "kerf", the extra length lost to sawdust when a sawcut is made; you should ignore it, too.
    
    FJ sadly realizes that he doesn't own a saw with which to cut the wood, so he mosies over to Farmer Don's Farm with this long board and politely asks if he may borrow a saw.
    
    Farmer Don, a closet capitalist, doesn't lend FJ a saw but instead offers to charge Farmer John for each of the N-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.
    
    Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create the N planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.
    
    Input
    
    Line 1: One integer N, the number of planks 
    Lines 2..N+1: Each line contains a single integer describing the length of a needed plank
    Output
    
    Line 1: One integer: the minimum amount of money he must spend to make N-1 cuts
    Sample Input
    
    3
    8
    5
    8
    Sample Output
    
    34
    Hint
    
    He wants to cut a board of length 21 into pieces of lengths 8, 5, and 8. 
    The original board measures 8+5+8=21. The first cut will cost 21, and should be used to cut the board into pieces measuring 13 and 8. The second cut will cost 13, and should be used to cut the 13 into 8 and 5. This would cost 21+13=34. If the 21 was cut into 16 and 5 instead, the second cut would cost 16 for a total of 37 (which is more than 34).
    View Code

       哈夫曼数的原理。将流程绘成一颗二叉树即可。

     1 #include <iostream>
     2 #include <vector>
     3 #include <limits.h>
     4 #include <algorithm>
     5 #include <math.h>
     6 #include <functional>
     7 #include <queue>  
     8 using namespace std;
     9 
    10 const int MAX = 20000 + 5;
    11 const int INF = 0x3f3f3f3f; // 常用用法,防止溢出
    12 
    13 typedef long long LL;
    14 int N;
    15 priority_queue<LL, vector<LL>, greater<LL>> q;
    16 
    17 int main(){
    18     while (scanf("%d", &N) != EOF) {
    19         LL num;
    20         for (int i = 0; i < N; ++i) {
    21             scanf("%lld", &num);
    22             q.push(num);
    23         }
    24         LL cost = 0;
    25         while (!q.empty()) {
    26             int n1 = q.top(); q.pop();
    27             int n2 = q.top(); q.pop();
    28             cost += n1 + n2;
    29             if (q.empty())
    30                 break;
    31             q.push(n1 + n2);
    32         }
    33         printf("%lld
    ", cost);
    34     }
    35 
    36     return 0;
    37 }
    View Code

      

  • 相关阅读:
    Handling Errors and Exceptions
    Advanced Features of Delphi DLLs
    How to put a relative path for a DLL statically loaded?
    Delphi DLL制作和加载 Static, Dynamic, Delayed 以及 Shared-Memory Manager
    The useful App Paths registry key : HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionApp Paths
    DLL Dynamic-Link Library Search Order
    Can a windows dll retrieve its own filename?
    Restrict form resize -- Delphi
    Programmer in Google Code
    How to open a web site with the default web browser in a NEW window
  • 原文地址:https://www.cnblogs.com/Atanisi/p/8711543.html
Copyright © 2011-2022 走看看