• 51nod 贪心算法题集


    2070 最小罚款:

    题意:初始有n元,每个任务有2个参数:t和w,<=t时刻前完成任务才可避免造成损失w。问:如何安排才能尽可能避免损失?一个任务执行时间是一个单位时间。

    分析:任务按时间排个序,来一个储存每个任务w的最小堆。执行当前任务(相当于入堆),若发现执行后,时间并不超越自己的截止日期(当前时间是执行任务数,亦即当前堆size),那自然入堆,否则说明当前任务其实是不够位置放的,那么要做一个抉择:是否要保留当前任务?或者是把前面哪个要执行的任务踢出去。要踢出的自然是那个带来利益最小的了(堆顶元素)。 计算一下损失loss,n-loss即为解。

    #include <bits/stdc++.h>
    using namespace std;
    #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
    #define fi first
    #define se second
    const int maxN=1e5+5,inf=0x3f3f3f3f;
    pair<int,int> a[505];
    
    int main () {
      // freopen("data.in", "r", stdin);
      int n, m, loss = 0;
      scanf("%d%d", &n, &m);
      FOR(i, 0, m - 1) scanf("%d", &a[i].fi);
      FOR(i, 0, m - 1) scanf("%d", &a[i].se);
      sort(a, a + m);
      priority_queue<int> Q;
    
      FOR(i, 0, m - 1) {
        Q.push(-a[i].se);
        if ((int)Q.size() > a[i].fi) {
          loss += -Q.top();
          Q.pop();
        }
      }
      printf("%d
    ", n - loss);
      return 0;
    }

    1065 最小正子段和

    给一个数列,某一段连续的和为正的子序列和,称之为最小正子段和,求其最小值。

    由于是连续的,容易联想到前缀和。这里:最小正子段和由于连续,所以必然是某两个前缀和之差。记Si为前i项和,对结构体{Si, i}以Si排序,那么可知,最小正子段和必然是排序后的某两相邻项之差。因为:排序后为ABC,AC能构成正子段和的话,必然BC能构成,且BC的答案比AC更优。为什么?因为若AB不能构成,而AC能构成的话,说明posA < posC,又posA>posB,所以posB <posA<posC,那么posB和posC相对关系也是合法的。另:单独的前缀和也有可能是答案。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
    int a[50005], n;
    struct node {ll s, p;} nd[50005];
    bool cmp(node a, node b) {
      if (a.s != b.s) return a.s < b.s;
      else return a.p < b.p;
    }
    
    int main () {
      scanf("%d", &n);
      nd[0].s = nd[0].p = 0;
      FOR(i, 1, n) {
        scanf("%d", &a[i]);
        nd[i].s = nd[i - 1].s + a[i];
        nd[i].p = i;
      }
      sort(nd + 1, nd + 1 + n, cmp);
      ll ans = 2e9;
      FOR(i, 1, n) {
        if (nd[i].s > 0)  ans = min(ans, nd[i].s);
        if (nd[i].p > nd[i - 1].p) {
          ll dis = nd[i].s - nd[i - 1].s;
          if (dis > 0) ans = min(ans, dis);
        }
      }
      printf("%lld
    ", ans);
      return 0;
    }

    1099 任务执行顺序

    每个任务有执行空间R,执行完需存储空间O,相当于释放了R-O空间,满足R>=O,问如何排列任务能使得执行所有任务消耗的空间最少为多少?

    假设有任务1和2。先执行1,那么所需空间是max(R1,O1+R2),同理若先执行2,需要max(R2,O2+R1),假设先执行1更优,即是说:

    max(R1,O1+R2)<max(R2,O2+R1),那么只需满足;O1+R2<O2+R1即可。按照这个排序算一下总共需要的空间即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
    struct node{ll R, O;} a[100005];
    bool cmp(node a, node b){return a.O - a.R < b.O - b.R;}
    
    int main () {
      // freopen("data.in", "r", stdin);
      int n;
      scanf("%d", &n);
      FOR(i, 1, n) scanf("%lld%lld", &a[i].R, &a[i].O);
      sort(a + 1, a + 1 + n, cmp);
      ll ans = 0, cur = 0;
      FOR(i, 1, n) {
        if (cur < a[i].R)
          ans += a[i].R - cur, cur = a[i].R;
        cur -= a[i].O;
      }
      printf("%lld
    ", ans);
      return 0;
    }

    1449 砝码称重

    现在有好多种砝码,他们的重量是w^0,w^1,w^2,.... 每种各一个。问用这些砝码能不能表示一个重量为m的东西。假设w为3,m为7,可以将重物和3放到一个托盘中,9和1放到另外一个托盘中。

    可以输出YES,否则NO。相当于问是否存在两个w进制的数a和b,其中每位仅为0/1,且a和b没有相同位置的1,使得a+m=b。思路:先将m利用辗转相除法变成w进制的数字。从低到高遍历这个数字,若当前位为0 or 1,则在b的对应位放0 or 1,a处0即可,若是m对应位为w-1,即需要a在对应位来个1,使得b处变成0,且m有一个进位,若m对应位非0非1非w-1,则“NO"

    比较容易理解的写法:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll a[105];
    int main() {
      ll w,m,p=0;
      scanf("%lld%lld", &w, &m);
      while (m)
        a[p++]=m%w, m/=w;
      for (int i = 0; i < p; ++i) {
        if (a[i] == 0 || a[i] == 1) continue;
        if (a[i] == w - 1) a[i + 1]++;
        else {
          puts("NO");
          return 0;
        }
      }
      puts("YES");
      return 0;
    }

    可以再简化,方法是一样的。

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    int main () {
      ll w, m, t;
      scanf("%lld%lld", &w, &m);
      while (m) {
        t = m % w;
        if (t == 0 || t == 1) m = m / w;
        else if (t == w - 1) m = m / w + 1;
        else {
          puts("NO");
          return 0;
        }
      }
      puts("YES");
      return 0;
    }
  • 相关阅读:
    [整] Android Fragment 生命周期图
    LruCache--远程图片获取与本地缓存
    Android基于XMPP Smack openfire 开发的聊天室
    基于XMPP协议的Android即时通信系
    Android实现推送方式解决方案
    日历工具类(一)——公历农历互相转换
    IdHTTPServer使用注意问题
    用TIdIPWatch获取本地IP
    delphi TStringList 用法详解
    WIN7 64位配置X86 MySQL 数据源
  • 原文地址:https://www.cnblogs.com/Rosebud/p/9832487.html
Copyright © 2020-2023  润新知