第六天训练做题小结
为什么没有第5天,因为年轻人不讲5的(其实是因为线段树太难了不会写呜呜呜回头再补上)
今天主要讲的是贪心算法。
贪心算法其实就是对这一步考虑,并且这一步在一定程度上不受之前的影响。
在今天的做题过程中,其实可以把目前遇到的题目归类一下
1.最短包装问题(如上课的例题,还有今天B - Length of Bundle Rope)
这种问题一般采用优先队列去解决,因为每次我需要求一个最短的和再放回进去再比较,也就是每次取两个最小的top()并且不要忘记pop()
Problem Description
Due to the development of online shopping, the logistics industry which is highly connectedwith goods shipping has been so prosperous that the great amount of employees is needed.Therefore, Alex, a truck driver in this growing industry, was supposed to transport severalparcels scattering in the warehouse to other cities in his daily routine.
According to the official safety requirements to the trucks running in the highway, Alex hadto tie up all the packages tightly so that he could settle the goods safely on his truck. Alexknew that the length of the cords needed for bundling the packages on the truck was based on the size of the packages themselves. Also, nn packages can be tied up well after n−1n−1 bundles.Moreover, when bundling goods, Alex could only bundle two packages at one time to avoidscattering. Since the daily consumption of the cord was great and Alex was supposed to payfor it, he hopes to bundle all the goods with the shortest cord.
For example, there are 4 parcels in the size of 8, 5, 14, and 26 respectively. If Alex binds thefirst two together, the needed rope will be in the length of 13 (8+5 = 13) while the needed ropefor the latter two packages will be 40 (14 + 26 = 40). If Alex keeps bundling these two items,the rope length he needs will be 53 (13 + 40 = 53). So the total length of the 4 packages willbe 106 (13 + 40 + 53 = 106). If Alex tries another way by bundling the first two (8 + 5 = 13),adding up the third one (13 + 14 = 27), and then bundling the last item (27 + 14 = 53), he willonly need the cord in the length of 93 (13 + 27 + 53 = 93). Now your mission is to help Alexfinding the minimum length of the needed cord.
Input Format
The first line contains an integer TT indicating the number of test cases. Each test case contains two lines. The first one contains a positive integer nn indicating the number of packages. The second one contains n positive integers separated by a space to indicate the size of each parcel.
Output Format
For each test case, output the minimum length of the bundle rope required to tie all parcelstogether in one line.
Technical Specification
- 1≤T≤101≤T≤10
- 1≤n≤10001≤n≤1000
- The size of each parcel is at most 10001000.
这是b题的描述,接下来是b题的代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=1e4+10;
int a[maxn];
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&n);
q.push(n);
}
int sum=0;
int ans=0;
while(q.size()>1)
{
int x=q.top();
q.pop();
int y=q.top();
q.pop();
sum=sum+x+y;
q.push(x+y);
}
printf("%d\n",sum);
while(!q.empty())
{
q.pop();
}
}
return 0;
}
题型二:关于区间问题中进行贪心算法
在今天的题目中,C - 今年暑假不AC 给了一些时间过程,而我需要选择最多的时间段,方法就是对其中一个区间组成部分,结束时间进行sort
D - Monster 打怪的话其实刚开始考虑的是血量和攻击比,实际上是不正确的。对于任意两只怪物都需要考虑在一定时间内哪只怪物先击杀后续带来的血量最少也就是最优(体现了贪心的局部最优)
One day, v11 encounters a group of monsters in a foreast. In order to defend the homeland, V11 picks up his weapon and fights!
All the monsters attack v11 at the same time. Every enemy has its HP, and attack value ATK. In this problem, v11 has his ATK and infinite HP. The damage (also means reduction for HP) is exactly the ATK the attacker has. For example, if v11's ATK is 13 and the monster's HP is 27, then after v11's attack, the monster's HP become 27 - 13 = 14 and vice versa.
v11 and the monsters attack each other at the same time and they could only attack one time per second. When the monster's HP is less or equal to 0 , we think this monster was killed, and obviously it would not attack any more. For example, v11's ATK is 10 and a monster's HP is 5, v11 attacks and then the monster is killed! However, a monster whose HP is 15 will be killed after v11 attack for two times. v11 will never stop until all the monsters are killed ! He wants to minimum the HP reduction for the fight! Please note that if in some second, some monster will soon be killed , the monster's attack will works too.
InputThe first line is one integer T indicates the number of the test cases. (T <=100)
Then for each case, The first line have two integers n (0<n<=10000), m (0<m<=100), indicates the number of the monsters and v11's ATK . The next n lines, each line has two integers hp (0<hp<=20), g(0<g<=1000) ,indicates the monster's HP and ATK.OutputOutput one line.
First output “Case #idx: ”, here idx is the case number count from 1. Then output the minimum HP reduction for v11 if he arrange his attack order optimal .Sample Input
2 3 1 1 10 1 20 1 40 1 10 7 3
Sample Output
Case #1: 110 Case #2: 3
题面如上
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn=1e7+10;
typedef struct
{
double hp,att,cs;
}node;
int cmp(node &a,node &b)
{
return (a.att+b.att)*a.cs+b.att*b.cs<(a.att+b.att)*b.cs+a.att*a.cs;//判断条件
}
node a[maxn];
int main()
{
int q;
scanf("%d",&q);
for(int u=1;u<=q;u++)
{
int n;
double m;
scanf("%d %lf",&n,&m);
double sum=0;
for(int i=1;i<=n;i++)
{
scanf("%lf %lf",&a[i].hp,&a[i].att);
sum+=a[i].att;
a[i].cs=ceil(a[i].hp/m);
}
sort(a+1,a+1+n,cmp);
double ans=0;
int num=1;
while(num<=n)
{
ans+=a[num].cs*sum;
sum-=a[num].att;
num++;
}
printf("Case #%d: %.0f\n",u,ans);
}
return 0;
}
f题中可以直接从后往前判断刚开始的写法非常麻烦
钓鱼大师是一道很好的题目
G - Fishing Master
There are nn fish in the pool. For the ii - thth fish, it takes at least titi minutes to stew(overcook is acceptable). To simplify this problem, the time spent catching a fish is kk minutes. You can catch fish one at a time and because there is only one pot, only one fish can be stewed in the pot at a time. While you are catching a fish, you can not put a raw fish you have caught into the pot, that means if you begin to catch a fish, you can't stop until after kk minutes; when you are not catching fish, you can take a cooked fish (stewed for no less than titi) out of the pot or put a raw fish into the pot, these two operations take no time. Note that if the fish stewed in the pot is not stewed for enough time, you cannot take it out, but you can go to catch another fish or just wait for a while doing nothing until it is sufficiently stewed.
Now eomeom wants you to catch and stew all the fish as soon as possible (you definitely know that a fish can be eaten only after sufficiently stewed), so that he can have a satisfying meal. If you can complete that in the shortest possible time, eomeom will accept you as his apprentice and say "I am done! I am full!". If you can't, eomeom will not accept you and say "You are done! You are fool!".
So what's the shortest time to pass the trial if you arrange the time optimally?
For each test case, the first line contains two integers n(1≤n≤105),k(1≤k≤109)n(1≤n≤105),k(1≤k≤109), denoting the number of fish in the pool and the time needed to catch a fish.
the second line contains nn integers, t1,t2,…,tn(1≤ti≤109)t1,t2,…,tn(1≤ti≤109) ,denoting the least time needed to cook the ii - thth fish.OutputFor each test case, print a single integer in one line, denoting the shortest time to pass the trial.Sample Input
2 3 5 5 5 8 2 4 3 3Sample Output
23
11
Hint
Case 1: Catch the 3rd fish (5 mins), put the 3rd fish in, catch the 1st fish (5 mins), wait (3 mins),
take the 3rd fish out, put the 1st fish in, catch the 2nd fish(5 mins),
take the 1st fish out, put the 2nd fish in, wait (5 mins), take the 2nd fish out.
Case 2: Catch the 1st fish (4 mins), put the 1st fish in, catch the 2nd fish (4 mins),
take the 1st fish out, put the 2nd fish in, wait (3 mins), take the 2nd fish out.
//这道题的话我是先考虑时间的问题,因为钓鱼时间是肯定不会变的,但是如果按照给定钓鱼次数然后去对后面的煮鱼时间讨论,可能时间会有浪费
因此的话先考虑鱼的时间,然后再去考虑每次煮鱼可以吊多少fish
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
int a[100010];
using namespace std;
int main()
{
int t;
cin>>t;
int n,k;
while(t--)
{
scanf("%d %d",&n,&k);
int cs=0;
long long time=k;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
time+=a[i];
cs+=a[i]/k;
a[i]=a[i]%k;
}
sort(a+1,a+1+n);
if(cs>=n-1)
{
printf("%lld\n",time);
}
else
{
for(int i=n;i>=1;i--)
{
cs++;
time=time+k-a[i];
if(cs>=n-1)
{
printf("%lld\n",time);
break;
}
}
}
}
return 0;
}
//代码如上
不能老是摸鱼了,要加油了不然今年春天连打比赛的资格都没有呜呜呜

浙公网安备 33010602011771号