贪心专题:简单贪心和区间贪心

FatMouse’ Trade

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 122539 Accepted Submission(s): 42325

Problem Description
FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean.
The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and requires F[i] pounds of cat food. FatMouse does not have to trade for all the JavaBeans in the room, instead, he may get J[i]* a% pounds of JavaBeans if he pays F[i]* a% pounds of cat food. Here a is a real number. Now he is assigning this homework to you: tell him the maximum amount of JavaBeans he can obtain.

Input
The input consists of multiple test cases. Each test case begins with a line containing two non-negative integers M and N. Then N lines follow, each contains two non-negative integers J[i] and F[i] respectively. The last test case is followed by two -1’s. All integers are not greater than 1000.

Output
For each test case, print in a single line a real number accurate up to 3 decimal places, which is the maximum amount of JavaBeans that FatMouse can obtain.

Sample Input
5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1

Sample Output
13.333
31.500
思路:相当于花钱买东西 每个东西单价不同 要买到最多重量的东西

#include<bits/stdc++.h>
using namespace std;
struct javabean{
    double w;//重量 
	double c;//花费 

} ; 
const int MAXN=1000+10; 
javabean arr[MAXN]; 
bool compare(javabean x,javabean y){
   return (x.w/x.c)>(y.w/y.c);//一磅猫粮换的豆越多越好  
}
 
int main(){
	int m,n;//m猫粮 n间房 
	while(cin>>m>>n){
		if(m==-1||n==-1) break; 
		double s=0;//最后可以换的最大豆子数量 
		for(int i=0;i<n;i++){
			cin>>arr[i].w>>arr[i].c; 
		} 
		sort(arr,arr+n,compare);
		for(int i=0;i<n;i++){
			if(m>=arr[i].c){
			   m-=arr[i].c;
			   s+=arr[i].w; 
			}
			else{//剩下的猫粮不够换全部的豆子 则换部分 
			   s+=arr[i].w*(m/arr[i].c);
			   m=0; 
			   break;
			}
		 
			 
		}
		printf("%.3f\n",s);	
	}
	return 0;
 
}
/*
5 3
7 2
4 3
5 2
20 3
25 18
24 15
15 10
-1 -1

*/
 

Senior’s Gun

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3095 Accepted Submission(s): 1020

Problem Description
Xuejiejie is a beautiful and charming sharpshooter.

She often carries n guns, and every gun has an attack power a[i].

One day, Xuejiejie goes outside and comes across m monsters, and every monster has a defensive power b[j].

Xuejiejie can use the gun i to kill the monster j, which satisfies b[j]≤a[i], and then she will get a[i]−b[j] bonus .

Remember that every gun can be used to kill at most one monster, and obviously every monster can be killed at most once.

Xuejiejie wants to gain most of the bonus. It’s no need for her to kill all monsters.

Input
In the first line there is an integer T, indicates the number of test cases.

In each case:

The first line contains two integers n, m.

The second line contains n integers, which means every gun’s attack power.

The third line contains m integers, which mean every monster’s defensive power.

1≤n,m≤100000, −109≤a[i],b[j]≤109。

Output
For each test case, output one integer which means the maximum of the bonus Xuejiejie could gain.

Sample Input
1
2 2
2 3
2 2

Sample Output
1
思路:打怪兽 因为要奖金最高 所以用最好的抢打最弱的怪兽 这样赚的差值越高

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const  int  maxn=100000+10;
long long gun[maxn];
long long monster[maxn];
bool cmp(long long a,long long b){
   return a>b;
}
int main(){
	int t;
    scanf("%d",&t); 
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m); 
		for(int i=0;i<n;i++){
		  scanf("%lld",&gun[i]);
		  
		}
		for(int i=0;i<m;i++){
		  scanf("%lld",&monster[i]);
		  
		}
		sort(gun,gun+n,cmp);//从大到小
		sort(monster,monster+m); //从小到大	A 
		long long  s=0;
		for(int i=0;i<n;i++){
		   if(i>=m||gun[i]<=monster[i]) {//没怪兽了  怪兽的下标不超过m   =m时越界
		        break;  
		    }
		    s+=gun[i]-monster[i];//i<m i<n  
		}
		printf("%lld\n",s);//long long 型的 
	
	}
	 


}

. 箱子打包

单点时限: 2.0 sec

内存限制: 256 MB

有一组 1 维的物品需要打包进一批同样的箱子中。所有的箱子有完全一样的长度 l 以及每一个物品长度 li<=l. 我们要找到一个最小的数字 q, 使得 :

(1) 每个箱子最多包含两个物品

(2) 每个物品要被包含在 q 个箱子中的一个中

(3) 在箱子中物品的总长度不能超过 l

你的任务是,给定 n 个整数,l,l1,l2…ln, 计算最小的箱子总数 q.

输入格式
第一行包含一个数字 n(1<= n <= 10^5), 表示有几个物品。第二行包含一个整数表示了箱子的长度 l (l<=10000). 接下去的 n 行是表示了每个物品的长度。

输出格式
输出一个整数,表示能够包含所有物品的最小的箱子总数。
提示 :

The sample instance and an optimal solution is shown in the figure below. Items are numbered from 1 to 10 according to the input order.

在这里插入图片描述

样例
input
10
80
70
15
30
35
10
80
20
35
10
30
output
6





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

const int maxn=1e5+10;
int length[maxn];
int main(){
	int n,len;
	scanf("%d%d",&n,&len);//输入物品数目和每个箱子长度 
	for(int i=0;i<n;i++){
	 scanf("%d",&length[i]);
	}
	sort(length,length+n);
	int l=0;
	int r=n-1;
	int s=0;
    while(l<=r){//当l=r  指向同一个物品 不管满足if和else的哪个都会使得s++  然后跳出循环 
    	if(length[r]+length[l]>len){//说明最大的只可以单独装 不能再放最小的 
    		r--;
			 
		}
		else{//说明装的小的和大的可以一起装 
			l++;
			r--;
		} 
	    s++;//每次操作都会增加一个箱子  
    }
    
    
    printf("%d\n",s); 
	  return 0; 
  
	
	
	
}


或者 中间while处写成


 while(l<=r){
        if(l==r){
		   s++;//当l=r  指向同一个物品  用一个箱子装 跳出循环
		   break;  
		   
		}
         
    	if(length[r]+length[l]>len){//说明最大的只可以单独装 不能再放最小的 
    		r--;
    		s++; 
			 
		}
		else{//说明装的小的和大的可以一起装 
			l++;
			r--;
			s++;
		} 
	      
    }


Aggressive cows

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 32128 Accepted: 14709
Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,…,xN (0 <= xi <= 1,000,000,000).

His C (2 <= C <= N) cows don’t like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?
Input

  • Line 1: Two space-separated integers: N and C

  • Lines 2…N+1: Line i+1 contains an integer stall location, xi
    Output

  • Line 1: One integer: the largest minimum distance
    Sample Input

5 3
1
2
8
4
9
Sample Output

3
Hint

OUTPUT DETAILS:

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.

Huge input data,scanf is recommended.

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; 
const int maxn=1e5+10;
int arr[maxn]; 
bool judge(int n,int m,int dis){//n个点 m头牛  距离dis 
	 int number=1;//已经放的牛的数量 
	 int current=arr[0];//现在在arr[0]处放一只牛 
	 for(int i=1;i<n;i++){//在各个点试着放牛 看距离是否大于dis 
	 	if(arr[i]-current>=dis){//说明在这个点可以放牛 牛的数量++ 更新current 下次以current为基准 
	 		number++; 
	 		current=arr[i];
	 	}
	 	if(number>=m){
	
	 		return true;//说明已经放完m头牛 
	 	} 
	 	
	 }
	 return false; 
	 
 }
int main(){
   int n,m;
   cin>>n>>m;
   for(int i=0;i<n;i++){
   	 cin>>arr[i];
   } 
   sort(arr,arr+n); 
   int l=0;
   int r=arr[n-1]-arr[0];
   while(l<=r){
   	  int mid=l+(r-l)/2; 
   	  if(judge(n,m,mid)){//如果在mid处可以放牛 把他扩大 
   	  	 l=mid+1; 
   	  }
   	  else{//放不了 则缩小一点 
   	  	 r=mid-1; 
   	  }
   }
   printf("%d\n",r);//跳出循环 r<l 此时最大的最小距离就是r-0 即为r 
   
   return 0; 
} 

Drying

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 31790 Accepted: 7867
Description

It is very hard to wash and especially to dry clothes in winter. But Jane is a very smart girl. She is not afraid of this boring process. Jane has decided to use a radiator to make drying faster. But the radiator is small, so it can hold only one thing at a time.

Jane wants to perform drying in the minimal possible time. She asked you to write a program that will calculate the minimal time for a given set of clothes.

There are n clothes Jane has just washed. Each of them took ai water during washing. Every minute the amount of water contained in each thing decreases by one (of course, only if the thing is not completely dry yet). When amount of water contained becomes zero the cloth becomes dry and is ready to be packed.

Every minute Jane can select one thing to dry on the radiator. The radiator is very hot, so the amount of water in this thing decreases by k this minute (but not less than zero — if the thing contains less than k water, the resulting amount of water will be zero).

The task is to minimize the total time of drying by means of using the radiator effectively. The drying process ends when all the clothes are dry.

Input

The first line contains a single integer n (1 ≤ n ≤ 100 000). The second line contains ai separated by spaces (1 ≤ ai ≤ 109). The third line contains k (1 ≤ k ≤ 109).

Output

Output a single integer — the minimal possible number of minutes required to dry all clothes.

Sample Input

sample input #1
3
2 3 9
5

sample input #2
3
2 3 6
5
Sample Output

sample output #1
3

sample output #2
2

题目大意:

有一些衣服,每件衣服有一定水量,有一个烘干机,每次可以烘一件衣服,每分钟可以烘掉k滴水。每件衣服没分钟可以自动蒸发掉一滴水,用烘干机烘衣服时不蒸发。问最少需要多少时间能烘干所有的衣服。

解题分析

本题用二分答案求解,解题思路就是二分时间,再对每个物品依据当前二分的时间进行判断,如果该物品水量小于等于总时间,那么就等其自然风干即可,如果大于总时间,那么要使当前枚举的答案成立,该衣服必然要消耗一定的机器清洗时间,算出所有衣服需要消耗的时间,将其与枚举的答案比较,即可判断答案的正确性。

假设当前枚举的总共清洗时间为mid,衣服水量为a[i],需要机洗x分钟,那么必然需要满足等式 x*k+mid-x>=a[i] ,整理之后可得:x>=(a[i]-mid)/(k-1),因为x依据题意只能取整数,所以我们需要用到ceil()函数来向上取整,得到符合条件的最小x值,注意,由于除数不能为0,所以k==1是需要特判一下。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int water[maxn];
int judge(int n,int k,int time){//n件衣服  烘干机的能力k 时间time 
	int s=0;
	for(int i=0;i<n;i++){
		if(water[i]>time){
			s+=ceil((water[i]-time)*1.0/(k-1));
		} 
		if(s>time){
			return false;
		}
	}
	return true;
	
	
}
int main(){
	int n;
	int k;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
	   scanf("%d",&water[i]);
	} 
	scanf("%d",&k);
	sort(water,water+n);//含水量从小到大排序 
	if(k==1){
		printf("%d\n",water[n-1]);//如果k==1 直接自然烘干 就是含水量最多的那件衣服的时间 
	}
	else{
			int l=1;//最少时间1分钟 
			int r=water[n-1];//最多时间water[n-1] 
			while(l<=r){
				int mid=l+(r-l)/2;
				if(judge(n,k,mid)){//在mid内可以洗 看能不能压缩时间使时间更短 
					r=mid-1; 
				}
				else{//在mid内时间不够 扩大时间 
					l=mid+1; 
				
				} 
			}
			printf("%d\n",l);//这是跳出循环 l比r大  选择l因为若时间够r更新 r减小使得跳出循环 但是新的r还没判断过 所以选l 
    }
	return 0;
	
	
}



今年暑假不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
思路:每次找结束时间最早的找不重叠的区间

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100+10; 
struct pro{
	int start;
	int end; 
} ;
pro p[maxn];
bool cmp(pro a,pro b){
	return  a.end<b.end; 
} 
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		for(int i=0;i<n;i++){
		   scanf("%d%d",&p[i].start,&p[i].end);
		}
		sort(p,p+n,cmp);
		int s=0;
		int current=0;
		for(int i=0;i<n;i++){
			if(current<=p[i].start){//说明不重叠区间 现在的区间结束长度小于下个区间的开始
			    current=p[i].end; 
			    s++; 
			}
		}	
		printf("%d\n",s);
		
		 
	} 
	return 0; 
}

Radar Installation

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 141827 Accepted: 31341
Description

Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d.

We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates.

Figure A Sample Input of Radar Installations

Input

The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases.

The input is terminated by a line containing pair of zeros
Output

For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. “-1” installation means no solution for that case.
Sample Input

3 2
1 2
-3 1
2 1

1 2
0 2

0 0
Sample Output

Case 1: 2
Case 2: 1

思路:以岛屿为核心 将雷达可建立的范围设为区间 就是找最多的重叠区间这样建的雷达就越少


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>  using namespace std; const int maxn=1000+10; struct interval{ 	double left; 	double right; }; bool cmp(interval a,interval b){ 	return a.left<b.left;  } 

interval arr[maxn]; //每个岛屿的区间 

int main(){ 	int n,d; 	int casenum=0; 	while(scanf("%d%d",&n,&d)!=EOF){ 		if(n==0&&d==0) break; 		bool flag=true; 		for(int i=0;i<n;i++){ 			int x; 			int y;//每个岛屿的坐标  			scanf("%d%d",&x,&y); 			if(y>d) flag=false; 			else{
				arr[i].left=x-sqrt(d*d-1.0*y*y);
				arr[i].right=x+sqrt(d*d-1.0*y*y);
				 			}	  		}  		if(!flag){ 			printf("Case %d: %d\n",++casenum,-1); 		}  		else{//在可行的区间内找最多重叠的部分  			sort(arr,arr+n,cmp);  			double current=arr[0].right;  			int answer=1; 			for(int i=1;i<n;i++){
				if(arr[i].left<=current){//重叠 用一个雷达就够 
				      current=min(current,arr[i].right);//使得重叠区间的基准更小 更新重叠点每次取最小的右端点 
				}
				else{//不重叠 找下一个区间 得多建立一个雷达 
				   current=arr[i].right; 
				   answer++; 
				} 
				
			  			} 			printf("Case %d: %d\n",++casenum,answer); 		} 
		
		
		 	} 	return 0;  	 }

题目描述

在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果合成一堆。每一次合并,小明可以把两堆水果合并到一起,消耗的体力等于两堆水果的重量之和。当然经过 n‐1 次合并之后,就变成一堆了。小明在合并水果时总共消耗的体力等于每次合并所耗体力之和。 假定每个水果重量都为 1,并且已知水果的种类数和每种水果的数目,你的任务是设计出合并的次序方案,使小明耗费的体力最少,并输出这个最小的体力耗费值。例如有 3 种水果,数目依次为 1,2,9。可以先将 1,2 堆合并,新堆数目为3,耗费体力为 3。然后将新堆与原先的第三堆合并得到新的堆,耗费体力为 12。所以小明总共耗费体力=3+12=15,可以证明 15 为最小的体力耗费值。

输入描述:
每组数据输入包括两行,第一行是一个整数 n(1<=n<=10000),表示水果的种类数。第二行包含 n 个整数,用空格分隔,第 i 个整数(1<=ai<=1000)是第 i 种水果的数目。
输出描述:
对于每组输入,输出一个整数并换行,这个值也就是最小的体力耗费值。输入数据保证这个值小于 2^31。
示例1
输入
3
9 1 2
0
输出
15

思路:哈夫曼树 每次找序列中最小的两个合并 且合并的要放回去再比较

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=10000+10;

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        if(n==0)break;
        else{
            priority_queue<int,vector<int>,greater<int>> q;
            while(n--){
                int x;
                scanf("%d",&x);
                q.push(x);
            }
            int answer=0;
            while(q.size()>1){
                int a=q.top();
                q.pop();
                int b=q.top();
                q.pop();
                answer+=a+b;
                q.push(a+b);
            }
            printf("%d\n",answer);  
        }
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值