zoukankan      html  css  js  c++  java
  • 51nod 贪心系列

    贴代码 水题

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e4+4;
     4 int ans;
     5 int cnt[27];
     6 int main()
     7 {
     8     char c;
     9     while(~scanf("%c",&c))
    10     {
    11         if((c>='a'&&c<='z')||(c>='A'&&c<='Z')) 
    12         {
    13             if(c>='A'&&c<='Z') cnt[c-'A']++;
    14             else cnt[c-'a']++; 
    15         }
    16         else break;
    17     }
    18     sort(cnt,cnt+26);
    19     for(int i=0;i<26;i++)
    20     {
    21         ans+=cnt[i]*(i+1);
    22     }
    23     printf("%d
    ",ans);
    24 }
     
     
     
    基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题
     收藏
     关注
    有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格子走出去。机器人有一个初始能量,每个格子对应一个整数A[i],表示这个格子的能量值。如果A[i] > 0,机器人走到这个格子能够获取A[i]个能量,如果A[i] < 0,走到这个格子需要消耗相应的能量,如果机器人的能量 < 0,就无法继续前进了。问机器人最少需要有多少初始能量,才能完成整个旅程。
     
    例如:n = 5。{1,-2,-1,3,4} 最少需要2个初始能量,才能从1号走到5号格子。途中的能量变化如下3 1 0 3 7。
    Input
    第1行:1个数n,表示格子的数量。(1 <= n <= 50000)
    第2 - n + 1行:每行1个数A[i],表示格子里的能量值(-1000000000 <= A[i] <= 1000000000)
    Output
    输出1个数,对应从1走到n最少需要多少初始能量。
    Input示例
    5
    1
    -2
    -1
    3
    4
    Output示例
    2

    思路很简单 就是模拟一下走过去的过程 如果发发现当前携带能量值 不够了 就再加上 先假设某一种可行的
    方案走下去 中间遇到更优或者不可行的地方 再进行修改 是一种很重要的贪心思想
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn=5e4+5;
     5 int n;
     6 LL sum;
     7 LL ans;
     8 int main()
     9 {
    10     scanf("%d",&n);
    11     int x;
    12     for(int i=0;i<n;i++)
    13     {
    14         scanf("%d",&x);
    15         sum+=x;
    16         if(sum<0){
    17             ans+=-sum;
    18             sum=0;
    19         }
    20     }
    21     printf("%lld
    ",ans);
    22 }
    
    
    基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题
     收藏
     关注
    
    
    X轴上有N条线段,每条线段包括1个起点和终点。线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]。
    给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长的。输出这个最长的距离。如果没有重叠,输出0。
     
    
    
    Input
    第1行:线段的数量N(2 <= N <= 50000)。
    第2 - N + 1行:每行2个数,线段的起点和终点。(0 <= s , e <= 10^9)
    Output
    输出最长重复区间的长度。
    Input示例
    5
    1 5
    2 4
    2 8
    3 7
    7 9
    Output示例
    4
    思路是 首先将所有区间按照左端点从小到大进行排序 右端点从大到小 ,
    从前向后扫一遍 每次记录在此之前的最大的右端点值 比较当前左端点与记录的值 即可计算出区间长度
    每次更新即可
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef pair<int,int> pii;
     5 const int maxn=5e4+5;
     6 vector< pii >a;
     7 
     8 int cmp(pii u, pii v)
     9 {
    10     return u.first==v.first?u.second>v.second:u.first<v.first;
    11 }
    12 
    13 int n;
    14 
    15 int main()
    16 {
    17     scanf("%d",&n);
    18     int x,y;
    19     for(int i=0;i<n;i++)
    20     {
    21         scanf("%d%d",&x,&y);
    22         a.push_back({x,y});
    23     }
    24     sort(a.begin(),a.end(),cmp);
    25     int ans=0;
    26     int tmp=a[0].second;
    27     for(int i=1;i<a.size();i++)
    28     {
    29         if(a[i].first>=tmp) tmp=a[i].second;
    30         else{
    31             ans=max(min(tmp,a[i].second)-a[i].first,ans);
    32             tmp=max(tmp,a[i].second);
    33         }
    34     }
    35     printf("%d
    ",ans);
    36 }
     
     
    基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
     收藏
     关注
    有若干个活动,第i个开始时间和结束时间是[Si,fi),同一个教室安排的活动之间不能交叠,求要安排所有活动,最少需要几个教室? 
    Input
    第一行一个正整数n (n <= 10000)代表活动的个数。
    第二行到第(n + 1)行包含n个开始时间和结束时间。
    开始时间严格小于结束时间,并且时间都是非负整数,小于1000000000
    Output
    一行包含一个整数表示最少教室的个数。
    Input示例
    3
    1 2
    3 4
    2 9
    Output示例
    2
    思路是 按照左端点将所有区间排序 然后从前向后 模拟一遍添加工作流水线的过程 
    用一个最小堆记录 当前使用的教室 的结束时间,如果发现当前有可以重复使用的空闲教室 就去使用它
    同时更新这个教室的结束时间
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e4+5;
     4 typedef pair<int,int> pii;
     5 vector<pii >a;
     6 
     7 int main()
     8 {
     9     int n;
    10     scanf("%d",&n);
    11     int x,y;
    12     for(int i=0;i<n;i++)
    13     {
    14         scanf("%d%d",&x,&y);
    15         a.push_back({x,y});
    16     }
    17     sort(a.begin(),a.end());
    18     priority_queue<int,vector<int>,greater<int> >p;
    19     int ans=1;
    20     p.push(a[0].second);
    21     for(int i=1;i<a.size();i++)
    22     {
    23         int pre=p.top();
    24         if(a[i].first<pre){
    25             ans++;
    26             p.push(a[i].second);
    27         }
    28         else{
    29             p.pop();
    30             p.push(a[i].second);
    31         }
    32     }
    33     printf("%d
    ",ans);
    34 }
    
    
    基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
     收藏
     关注
    有N个任务,每个任务有一个最晚结束时间以及一个对应的奖励。在结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。
    Input
    第1行:一个数N,表示任务的数量(2 <= N <= 50000)
    第2 - N + 1行,每行2个数,中间用空格分隔,表示任务的最晚结束时间E[i]以及对应的奖励W[i]。(1 <= E[i] <= 10^9,1 <= W[i] <= 10^9)
    Output
    输出能够获得的最高奖励。
    Input示例
    7
    4 20
    2 60
    4 70
    3 40
    1 30
    4 50
    6 10
    Output示例
    230

    思路是 按照时间顺序排序 ,拿一个cnt来记录到当前位置 有多少个空位置 就还没有安排 如果有 就把当前
    位置安排过去 否则 用一个最小堆维护一下以前安排过的位置的值 看 是不是可以和最小的交换
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef pair<int,int> pii;
     4 typedef long long LL;
     5 const int maxn=5e4+5;
     6 vector<pii >a;
     7 int n;
     8 
     9 int cmp(pii u,pii v)
    10 {
    11     return u.first==v.first?u.second>v.second:u.first<v.first;
    12 }
    13 
    14 map<int,int>ma;
    15 
    16 int main()
    17 {
    18     int x,y;
    19     scanf("%d",&n);
    20     for(int i=0;i<n;i++)
    21     {
    22         scanf("%d%d",&x,&y);
    23         ma[x]++;
    24         a.push_back({x,y});
    25     }
    26     sort(a.begin(),a.end(),cmp);
    27     priority_queue<int,vector<int>,greater<int> >p;
    28     int pre=0;
    29     int cnt=0;
    30     LL sum=0;
    31     for(int i=0;i<n;i++)
    32     {
    33         cnt=cnt+a[i].first-pre;
    34         if(cnt>=1)
    35         {
    36             cnt--;
    37             p.push(a[i].second);
    38             sum+=a[i].second;
    39             pre=a[i].first;
    40         }
    41         else{
    42             if(a[i].second>p.top())
    43             {
    44                 sum-=p.top();
    45                 sum+=a[i].second;
    46                 p.pop();
    47                 p.push(a[i].second);
    48             }
    49         }
    50     }
    51     printf("%lld
    ",sum);
    52 }
    
    
    基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
     收藏
     关注
    
    
    有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分,最后储存计算结果需要占据O[i]个空间(O[i] < R[i])。
     
    例如:执行需要5个空间,最后储存需要2个空间。给出N个任务执行和存储所需的空间,问执行所有任务最少需要多少空间。
    
    
    Input
    第1行:1个数N,表示任务的数量。(2 <= N <= 100000)
    第2 - N + 1行:每行2个数R[i]和O[i],分别为执行所需的空间和存储所需的空间。(1 <= O[i] < R[i] <= 10000)
    Output
    输出执行所有任务所需要的最少空间。
    Input示例
    20
    14 1
    2 1
    11 3
    20 4
    7 5
    6 5
    20 7
    19 8
    9 4
    20 10
    18 11
    12 6
    13 12
    14 9
    15 2
    16 15
    17 15
    19 13
    20 2
    20 1
    Output示例
    135

    假设当前有r1,o1,r2,o2,
    先执行1,需要空间是 max(r1,o1+r2)
    先执行2,需要空间是 max(r2,o2+r1)
    按照这个关系排个序 从小到大 顺次取 模拟一下即可
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=100000+10;
     4 int n;
     5 typedef pair<int,int> pii;
     6 vector<pii >a;
     7 
     8 int cmp1(pii u,pii v)
     9 {
    10     return max(u.first,u.second+v.first)<max(v.first,v.second+u.first);
    11 }
    12 int cmp2(pii u,pii v)
    13 {
    14     return u.first-u.second>v.first-v.second;
    15 }
    16 
    17 int main()
    18 {
    19     int x,y;
    20     scanf("%d",&n);
    21     for(int i=0;i<n;i++)
    22         scanf("%d%d",&x,&y),a.push_back({x,y});
    23     sort(a.begin(),a.end(),cmp1);
    24     int tmp=0;
    25     int ans=0;
    26     int pre=0;
    27     int left=0;
    28     for(int i=0;i<n;i++)
    29     {
    30         int r=a[i].first,o=a[i].second;
    31         if(r>left){
    32             tmp=tmp+r-left;
    33             ans=max(tmp,ans);
    34             left=r-o;
    35             pre+=o;
    36         }
    37         else{
    38             left-=o;
    39             pre+=o;
    40         }
    41     }
    42     printf("%d
    ",ans);
    43 }
    
    
    
     
    题目来源: 河北大学算法艺术协会
    基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
     收藏
     关注
    一位老木匠需要将一根长的木棒切成N段。每段的长度分别为L1,L2,......,LN(1 <= L1,L2,…,LN <= 1000,且均为整数)个长度单位。我们认为切割时仅在整数点处切且没有木材损失。
    木匠发现,每一次切割花费的体力与该木棒的长度成正比,不妨设切割长度为1的木棒花费1单位体力。例如:若N=3,L1 = 3,L2 = 4,L3 = 5,则木棒原长为12,木匠可以有多种切法,如:先将12切成3+9.,花费12体力,再将9切成4+5,花费9体力,一共花费21体力;还可以先将12切成4+8,花费12体力,再将8切成3+5,花费8体力,一共花费20体力。显然,后者比前者更省体力。
    那么,木匠至少要花费多少体力才能完成切割任务呢?
     
    Input
    第1行:1个整数N(2 <= N <= 50000)
    第2 - N + 1行:每行1个整数Li(1 <= Li <= 1000)。
    Output
    输出最小的体力消耗。
    Input示例
    3
    3
    4
    5
    Output示例
    19
    思路是 这样的一个加和形成的是一个树结构 很明显 层次越高的节点对于加和的贡献度越大
    因此拿个堆维护下即可
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int main()
     4 {
     5     int n;
     6     scanf("%d",&n);
     7     int x;
     8     priority_queue<int,vector<int>,greater<int> >p;
     9     for(int i=0;i<n;i++)
    10     {
    11         scanf("%d",&x);
    12         p.push(x);
    13     }
    14     int ans=0;
    15     while(p.size()>1)
    16     {
    17         int a=p.top();
    18         p.pop();
    19         int b=p.top();
    20         p.pop();
    21         p.push(a+b);
    22         ans+=a+b;
    23     }
    24     printf("%d
    ",ans);
    25 }
    基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
     收藏
     关注
    在公司年会上,做为互联网巨头51nod掌门人的夹克老爷当然不会放过任何发红包的机会。
     
    现场有n排m列观众,夹克老爷会为每一名观众送出普通现金红包,每个红包内金额随机。
     
    接下来,夹克老爷又送出最多k组高级红包,每高级红包会同时给一排或一列的人派发 ,每高级红包的金额皆为x。
     
    派发高级红包时,普通红包将会强制收回。同时,每个人只能得到一个高级红包。(好小气!)
     
    现在求一种派发高级红包的策略,使得现场观众获得的红包总金额最大。
    Input
    第一行为n, m, x, k四个整数。
    
    1 <= n <= 10, 1 <= m <= 200
    1 <= x <= 10^9,0 <= k <= n + m
    
    接下来为一个n * m的矩阵,代表每个观众获得的普通红包的金额。普通红包的金额取值范围为1 <= y <= 10^9
    Output
    输出一个整数,代表现场观众能获得的最大红包总金额
    Input示例
    3 4 1 5
    10 5 7 2
    10 5 10 8
    3 9 5 4
    Output示例
    78



    由于行只有10,列有200,因此 枚举行被选中的情况 再去列位置贪心的找应该修改后更优的情况
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 int a[20][2020];
     6 LL col[220];
     7 LL c[220];
     8 int n,m,x,k;
     9 int main()
    10 {
    11     scanf("%d%d%d%d",&n,&m,&x,&k);
    12     for(int i=0;i<n;i++)
    13     {
    14         for(int j=0;j<m;j++)
    15         {
    16             scanf("%d",&a[i][j]);
    17             c[j]+=a[i][j];
    18         }
    19     }
    20     LL ans=0;
    21     for(int i=0;i<=(1<<n)-1;i++)
    22     {
    23         int tmp=i;
    24         vector<int>v;
    25         for(int j=0;j<n;j++)
    26         {
    27             if((tmp>>j)&1) v.push_back(j);
    28         }
    29         if(v.size()>k) continue;
    30         int cnt=k-v.size();
    31         cnt=min(cnt,m);
    32         for(int j=0;j<m;j++) col[j]=c[j];
    33         for(int j=0;j<v.size();j++)
    34         {
    35             for(int k=0;k<m;k++)
    36             {
    37                  col[k]=col[k]-a[v[j]][k]+x;
    38             }
    39         }
    40         LL ppp=0;
    41         priority_queue<LL,vector<LL>,greater<LL> >p;
    42         for(int j=0;j<m;j++) p.push(col[j]);
    43         while(cnt>0)
    44         {
    45             if(p.top()<1LL*n*x){
    46                 cnt--;
    47                 ppp+=1LL*n*x;
    48                 p.pop();
    49             }
    50             else break;
    51         }
    52         while(!p.empty())
    53         {
    54             ppp+=p.top();
    55             p.pop();
    56         }
    57         ans=max(ans,ppp);
    58     }
    59 
    60    printf("%lld
    ",ans);
    61 
    62 }
     
     
     
  • 相关阅读:
    一阶段11.16
    视频(一阶段)
    一阶段需求分析
    sprint计划会议内容
    金管家NABCD分析
    四则运算
    返回一个整数数组中最大子数组的和(首尾相连)
    四则运算
    返回一个二维数组最大子数组的和
    返回一个数组 最大子数组的和
  • 原文地址:https://www.cnblogs.com/hellohacker/p/7374227.html
Copyright © 2011-2022 走看看