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 }
 
 
 
原文地址:https://www.cnblogs.com/hellohacker/p/7374227.html