2021-1-26 贪心入门

A - Express Mail Taking

Besides on the traditional classes,Baby Volcano also needs to learn how to take the express mails.

Usually express mails are stored in cabinets. In Baby Volcano’s school,there are n cabinets in a row,numbered by 1 to n. The distance between two adjacent cabinets is 1, and the entrance is at the cabinet 1. Among all n cabinets,the one numbered k is special and it is used to enter the code and open the cabinet door.

Baby Volcano has m express mails to take,the i-th is in the cabinet ai.
Two express mails will not be stored in the same cabinet. Also there is no express mail in the cabinet k.

To prevent expresses from being stolen, Baby Volcano have to take these express mails one by one, starting at the entrance. Generally, if he wants to take the express mail i, he have to walk to cabinet k first to enter the code, and then walks to cabinet ai. After taking the last one,he walks to the entrance.

There are so many express mails to take, so Baby Volcano wants to find a taking order which minimize the distance he walks.

Input

The first line contains one integer T(1≤T≤100),the number of testcases.

For each test cases,the first line contains three integer n,m,k(1≤k≤n≤109,1≤m<min(n,106))

The next line contains m integer,the i-th stand for ai(1≤ai≤n,ai≠k).

The input guarantees that ∑m≤2×106

Note:Because of the large input,it is prefered to use scanf instead of cin.

Output

For each test case,Output a single line contains one integer,representing for the minimal walking distance.

Sample Input

2
10 2 5
6 7
10 2 5
3 4

Sample Output

14
10

大致题意:

有T组测试数据,对于每组数据,有n个邮箱,要去m个邮箱取件,在第k个邮箱输入密码,求最小路径。

题解:
首先,对于每组情况,最先走的路径应该是从入口到密码箱,那么k-1的初始路径是必不可少的,然后就是不停的在取件箱和密码箱之间折返,对于任意情况路径都是相等的,唯一不同的是最后一个邮箱的位置(因为取完最后一个直接从入口离开了)。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

 int main(){
    
    
 	long long n,m,k,a[1000005];
 	int T;
	 scanf("%d",&T);
	 while(T--){
    
    
	 	scanf("%lld %lld %lld",&n,&m,&k);
	 	for(int i=0;i<m;i++)
	 	   scanf("%lld",&a[i]);
	 	sort(a,a+m);//经过排序,A柜离1最近 
	 	long long ans=k-1;//首先要去k柜
		for(int i=m-1;i>=1;i--){
    
    
			ans+=2*(abs(a[i]-k));//折返的路径
		} 
		if(a[0]<=k)ans+=k-1;
		else ans+=2*(abs(a[0]-k))+(k-1);
		printf("%lld\n",ans);
	 }   
	 return 0;	
 }

B - Length of Bundle Rope

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, n packages can be tied up well after
n−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

The first line contains an integer T indicating the number of test cases. Each test case contains two lines. The first one contains a positive integer n indicating the number of packages. The second one contains n positive integers separated by a space to indicate the size of each parcel.

1≤T≤10
1≤n≤1000
The size of each parcel is at most 1000.

Output

For each test case, output the minimum length of the bundle rope required to tie all parcelstogether in one line.

Sample Input

4
6
2 3 4 4 5 7
5
5 15 40 30 10
10
3 1 5 4 8 2 6 1 1 2
9
3 2 1 6 5 2 6 4 3

Sample Output

63
205
100
98

大致题意:
有T组测试数据,对于每组测试数据,先输入n,代表有n个礼物需要包。礼物两两之间需要包,两个包在一起的礼物可以自动理解为一个新礼物,要和剩下的礼物包在一起。输入的n个数代表包该礼物需要的绳子长度,两个包在一起的礼物需要的绳子长度等于两个礼物需要的绳子长度相加。

题解:
因为两个礼物包在一起之后,是拿他们俩的长度和再去和别的礼物的长度相加,所以包礼物的先后次序决定了该礼物长度被加的次数。所以只要将礼物长度数组每次排序,将最小的两个相加,直到礼物个数减为1就可以了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;


int main(){
    
    
	int T,n,a[1005];
	cin>>T;
	while(T--){
    
    
		cin>>n;
		for(int i=0;i<n;i++)
		   cin>>a[i];
		int sum=0;
		while(n>1){
    
    
			sort(a,a+n);
			a[0]+=a[1];
			sum+=a[0];
			n--;
			for(int i=1;i<n;i++)
			   a[i]=a[i+1];
		}
		printf("%d\n",sum);
	}
    return 0;
}

C - 今年暑假不AC

“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%…”

确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)

Input

输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。

Output

对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。

Sample Input

12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0

Sample Output

5

大致题意:
输入n个节目数,以0结尾。对于每个节目,都输入一个开始时间,以及一个结束时间,求出能尽可能多的看的节目数量。

题解:
首先默认第一个开始的节目可以看,然后只要将节目开始的时间排序,然后将看了的节目的结束时间和后续节目的开始时间进行比较,记录能够完整看的节目数即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>

 int main(){
    
    
 	int n,t,start[105],end[105];
 	while(~scanf("%d",&n)){
    
    
 		if(n==0)break;
 		for(int i=0;i<n;i++)
 		   scanf("%d %d",&start[i],&end[i]);

 		for(int i=0;i<n;i++)
 		   for(int j=i;j<n;j++){
    
    
 		   	   if(end[j]<end[i]){
    
    
 		   	   	   t=start[j];start[j]=start[i];start[i]=t;
 		   	   	   t=end[j];end[j]=end[i];end[i]=t;
				}
				
			}
	    int cnt=1;//默认能看第一个节目
	    int t=end[0];
		for(int i=1;i<n;i++){
    
    
			if(t<=start[i]){
    
    
			   cnt++;
			   t=end[i];}
		} 
		printf("%d\n",cnt);
	 }
 }

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.

Input

The 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.

Output

Output 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

大致题意:
有T组测试数据,对于每组数据,输入n个怪兽数量以及自己的攻击值。对于每个怪兽,输入血量和攻击值。要求输出受到的最小伤害值。

题解
因为自己的攻击值有限,所以不一定能将怪兽一次打死,所以不能先打攻击值大的(存在攻击值大血又厚的可能性)。所以考虑性价比的情况下,要打攻击值/血量大的,这样就可以尽量减少攻击值大的怪兽的攻击次数。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct node{
    
    
    long long hp;
    long long atk;
    long long time;
}monster[10005];

bool cmp(struct node &x,struct node &y){
    
    
    return (double)x.atk/x.time>(double)y.atk/y.time;
}

int main(){
    
    
    int T,n,m;
    scanf("%d",&T);
    for(int ii=1;ii<=T;ii++){
    
    //要改掉循环都用一个变量的习惯
    //防止造成变量在意想不到的时候被更改的可能
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
    
    
            scanf("%lld%lld",&monster[i].hp,&monster[i].atk);
            monster[i].time=(monster[i].hp/m+((monster[i].hp%m)?1:0));
        }
        sort(monster,monster+n,cmp);
        long long ans=0,time=0;
        for(int i=0;i<n;i++){
    
    
            time+=monster[i].time;
            ans+=(time*monster[i].atk);
        }
        printf("Case #%d: %lld\n",ii,ans);
    }
    return 0;
}

E题 Bet 贴一个标签
当时也没有想出来,看了偷来的链接,xdl


F - Boxers

There are n boxers, the weight of the i-th boxer is ai. Each of them can change the weight by no more than 1 before the competition (the weight cannot become equal to zero, that is, it must remain positive). Weight is always an integer number.

It is necessary to choose the largest boxing team in terms of the number of people, that all the boxers’ weights in the team are different (i.e. unique).

Write a program that for given current values ​ai will find the maximum possible number of boxers in a team.

It is possible that after some change the weight of some boxer is 150001 (but no more).

Input

The first line contains an integer n (1≤n≤150000) — the number of boxers. The next line contains n integers a1,a2,…,an, where ai (1≤ai≤150000) is the weight of the i-th boxer.

Output

Print a single integer — the maximum possible number of people in a team.

Sanmple Input

4
3 2 4 1
——————————————
6
1 1 1 4 4 4

Sample Output

4
——————————————
5

Note

In the first example, boxers should not change their weights — you can just make a team out of all of them.

In the second example, one boxer with a weight of 1 can be increased by one (get the weight of 2), one boxer with a weight of 4 can be reduced by one, and the other can be increased by one (resulting the boxers with a weight of 3 and 5, respectively). Thus, you can get a team consisting of boxers with weights of 5,4,3,2,1.

大致题意:
每次输入一个n,代表有n个运动员,再输入n个运动员的体重。然后计算最多有几个运动员可以去参加比赛就行了。只有不同体重的运动员才能去比赛,为了参加比赛,运动员的体重可以+1、不变、-1(当然前提是最终体重要大于0)。

题解:
只要将运动员按体重从小到大排序就行了,然后优先让运动员体重-1,即不影响后面的运动员,如果重复了,就不变,如果还重复,再考虑+1,因为+1很有可能会影响后面的运动员。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;


int main(){
    
    
	int n,a[150005],b[150005]={
    
    0};
	cin>>n;
	for(int i=0;i<n;i++)
	   cin>>a[i];
	sort(a,a+n);
	int sum=0;
	for(int i=0;i<n;i++){
    
    
		if((a[i]-1)>0&&b[a[i]-1]==0){
    
    
			b[a[i]-1]=1;
			sum++;
		}
		else if(b[a[i]]==0){
    
    
			b[a[i]]=1;
			sum++;
		}
		else if(b[a[i]+1]==0){
    
    
			b[a[i]+1]=1;
			sum++;
		}
	}
	printf("%d\n",sum);
    return 0;
}

G - Fishing Master

Heard that eom is a fishing MASTER, you want to acknowledge him as your mentor. As everybody knows, if you want to be a MASTER’s apprentice, you should pass the trial. So when you find fishing MASTER eom, the trial is as follow:

There are n fish in the pool. For the i - th fish, it takes at least ti minutes to stew(overcook is acceptable). To simplify this problem, the time spent catching a fish is k 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 k minutes; when you are not catching fish, you can take a cooked fish (stewed for no less than ti) 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 eom 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, eom will accept you as his apprentice and say “I am done! I am full!”. If you can’t, eom 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?

Input

The first line of input consists of a single integer T(1≤T≤20), denoting the number of test cases.

For each test case, the first line contains two integers 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 n integers, t1,t2,…,tn(1≤ti≤109) ,denoting the least time needed to cook the i - th fish.

Output

For 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 3

Sample Out

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.

大致题意:
有T组测试数据,对于每组测试数据,输入要抓的鱼数和抓鱼的时间。再输入烧每条鱼的时间,要求出最少的抓完和烧完所有鱼的时间。

题解:
首先,要烧鱼肯定是要抓鱼的。抓了第一条鱼以后,就可以一边烧鱼一边抓鱼了。抓鱼的时候显然是不能换鱼烧的,所以要尽量在抓鱼的时候烧 煮的时间比抓一条鱼时间久的 鱼(因为如果在抓完鱼之后还要烧鱼的话,显然烧 烧的时间比抓鱼时间更短的 鱼更节省时间)。然后如果烧一条鱼的时间比抓一条鱼的时间长,但比烧两条鱼的时间短的话,比烧一条鱼时间长的那段时间,可以和要放在抓完鱼之后烧的鱼(也就是烧的时间比抓一条鱼短的 鱼)进行比较,然后更短的放在后面烧。因为抓鱼的时间显然是不能避免的,能减少的只有抓完鱼后还要烧鱼的时间。

挖个坑,下次休息在这里放一张时间轴图,会比较清晰

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

bool cmp(long long a,long long b){
    
    
	return a>b;
}

int main(){
    
    
	long long T,n,k,a[100005];
	scanf("%lld",&T);
	while(T--){
    
    
		scanf("%lld %lld",&n,&k);
		long long temp=0;
		for(int i=1;i<=n;i++){
    
    
		   scanf("%lld",&a[i]);
		   temp+=a[i]/k;//记录有几个比钓一条鱼时间长的炖鱼时间段
	    }
	    long long time=k;//必须要先钓一条鱼才能炖鱼 
		if(temp>=n-1){
    
    //钓鱼时间能够被排满 
			for(int i=1;i<=n;i++){
    
    
				time+=a[i];
			}
		}
		else{
    
    
			for(int i=1;i<=n;i++){
    
    
				time+=a[i];
				a[i]=a[i]%k;
			}
			sort(a+1,a+n+1,cmp);
			for(int i=1;i<=(n-1)-temp;i++){
    
    
				time+=(k-a[i]);
			}
		}
		printf("%lld\n",time);
	}
    return 0;
}

贪心是一种思想,不是一种算法。

猜你喜欢

转载自blog.csdn.net/m0_52433146/article/details/113280088
今日推荐