东北林业大学 蓝桥杯新生培训-贪心 题解

前言:

  回校后参加的第一次训练,题目没有以往的那么多。

正文:

Problem:A  老鼠的旅行:

#include<bits/stdc++.h>
using namespace std;
struct sa{
	int j,f;
	double awk;
}data[10000];
int cmp(const sa &a,const sa &b){
	return a.awk>b.awk;
}
int main(){
	int n,m;
	while(cin>>m>>n){
		double sum=0,k=0;
		if(m==-1&&n==-1) break;
		for(int i=1;i<=n;i++){
			cin>>data[i].j>>data[i].f;
			data[i].awk=(double)data[i].j/(double)data[i].f;
		}
		sort(data+1,data+n+1,cmp);
		for(int i=1;i<=n;i++){
			if(m>=data[i].f){
				sum+=data[i].j;
				m-=data[i].f;
			}
			else{
				sum+=(double)m*data[i].awk;
				break;
			}
		}
		printf("%.3lf\n",sum);
	}
	return 0;
}

先将每个房间按性价比由高到低排序,再从前往后依次购买直至猫食用完(注意最后剩下的猫食不一定能买到整数)。

Problem:B Moving Tables:

#include<bits/stdc++.h>
using namespace std;
struct sa{
	int x,y,flag;
}data[501];
int cmp(const sa &a,const sa &b){
	if(a.x!=b.x) return a.x<b.x;
	else return a.y<b.y; 
}
int main(){
	int t,n,count,tmp;
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>data[i].x>>data[i].y;
			if(data[i].x>data[i].y){
				swap(data[i].x,data[i].y);
			}
			data[i].flag=0;
		}
		sort(data+1,data+n+1,cmp);
			count=0;
			for(int i=1;i<=n;i++){
				if(data[i].flag==1) continue;
				count++;tmp=i;data[i].flag=1;
				for(int o=i+1;o<=n;o++){
					if(!data[o].flag&&data[o].x>=data[tmp].y&&!(data[o].x%2==0&&(data[o].x-1==data[tmp].y))){//检验非对门 
					data[o].flag=1;tmp=o;
				}
			}
	}
	cout<<count*10<<endl;
	}
	return 0;
}

第一次做英文的题目,但还好题目意思比较容易理解,老师也讲了一遍。按照我的理解,每一次运输都要花相同的时间,我们就应该尽量让多条道路同时运输。假设我们先从第一次运输考虑,这次运输无论如何都要一次时间,理论上我们只需要找到有哪些房间可以在相同时间下一同运输就行了,然后往后遍历未选到的路(未标记的)。之后的路也同理(注意对门也不可以同时运)。

补:其实这道题无需排序也能过(sort和cmp函数可以删),我自己之后又在oj上试了一下。看来写博客的过程也是一个重新思考的过程,老师讲的时候下意识就按老师的想法走了,刚刚写博客的时候突然想到这sort排序好像没用,直接遍历是可行的,因为无论顺序如何,道路重叠和包含的是必须分开运的,事实上这题就是找重叠和包含的道路的数量。

#include<bits/stdc++.h>
using namespace std;
struct sa{
	int x,y,flag;
}data[501];
//int cmp(const sa &a,const sa &b){
//	if(a.x!=b.x) return a.x<b.x;
//	else return a.y<b.y; 
//}
int main(){
	int t,n,count,tmp;
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>data[i].x>>data[i].y;
			if(data[i].x>data[i].y){
				swap(data[i].x,data[i].y);
			}
			data[i].flag=0;
		}
		//sort(data+1,data+n+1,cmp);
			count=0;
			for(int i=1;i<=n;i++){
				if(data[i].flag==1) continue;
				count++;tmp=i;data[i].flag=1;
				for(int o=i+1;o<=n;o++){
					if(!data[o].flag&&data[o].x>=data[tmp].y&&!(data[o].x%2==0&&(data[o].x-1==data[tmp].y))){//检验非对门 
					data[o].flag=1;tmp=o;
				}
			}
	}
	cout<<count*10<<endl;
	}
	return 0;
}//这样也能过

Problem:C Wooden Sticks:

#include<bits/stdc++.h>
using namespace std;
struct sa{
	int x,y,flag;
}data[5009];
int cmp(const sa &a,const sa &b){
	return a.y<b.y;
}
int main(){
	int t,n,count,tmp;
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>data[i].x>>data[i].y;
			data[i].flag=0;
		}
		sort(data+1,data+n+1,cmp);
		count=0;
		for(int i=1;i<=n;i++){
			if(data[i].flag==1) continue;
			count++;data[i].flag=1,tmp=i;
			for(int o=i+1;o<=n;o++){
				if(!data[o].flag&&data[o].x>=data[tmp].x&&data[o].y>=data[tmp].y){
					data[o].flag=1;tmp=o;
				}
			}
		}
		cout<<count<<endl;
	}
	return 0;
}

先将木棍按宽或长有小到大排序,从最小宽或最小长的木棍遍历下去,找符合条件的木棍并标记,更新条件后再遍历,直至遍历到末尾,然后再从未标记的最前的木棍再往下遍历,直至结束。

Problem:D 今年暑假不AC:

#include<bits/stdc++.h>
using namespace std;
struct sa{
	int x,y;
}data[109];
int cmp(const sa &a,const sa &b){
	return a.y<b.y;
}
int main(){
	int n;
	while(cin>>n&&n!=0){
		int sum=1;
		for(int i=1;i<=n;i++){
			cin>>data[i].x>>data[i].y;
		}
		sort(data+1,data+n+1,cmp);
		sa tmp=data[1];
		for(int i=2;i<=n;i++){
			if(tmp.y<=data[i].x){
		//	cout<<sum<<" ";
			sum++;
			tmp=data[i];}
		}
		cout<<sum<<endl;
	}
	return 0;
}

事件序列问题中,如果在可能的事件a1<a2...an中选取在时间上不重叠的最长序列,那么一定存在
个包含a1 (结束最早)的最长序列。(证明:略)

这题也是排序后遍历并判断条件即可。

后记:

  比赛马上就要开始了,感觉自己没做啥准备,之后好好努力吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值