LOJ 一本通提高篇1.1貪心算法 練習

複習時食用,會比較簡略。


目錄

#10005. 「一本通 1.1 練習 1」數列極差

#10006. 「一本通 1.1 練習 2」數列分段

#10007. 「一本通 1.1 練習 3」線段

#10008. 「一本通 1.1 練習 4」家庭作業

#10009. 「一本通 1.1 練習 5」釣魚

#10010. 「一本通 1.1 練習 6」糖果傳遞


#10005. 「一本通 1.1 練習 1」數列極差

題目

題目大意

一個由n個正整數組成的數列,每次擦去其中的兩個數a和b。

然後在數列中加入一個數a*b+1,直至剩下一個數爲止。

按這種操作方式最後得到的數中,最大的爲max,最小的爲min。

該數列的極差定義爲M=max-min。

請對於給定的數列計算出相應的極差M。

對於全部數據,0<=n<=50000,保證所有數據計算均在32位有符號整數範圍內。

題目分析

surprise!神奇的規律!

要得到max每次就擦掉最大的兩個,要得到min每次就擦掉最小的兩個。

進行多次試驗尋找普遍規律。

肯定有什麼證明方法,看我腦筋急轉彎。還是不會。

代碼

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

int n,nn,x,a[50010],b[50010];
int cmp(int x,int y) { return x>y; }

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		a[i]=b[i]=x;
	}
	scanf("%d",&x);
	
	sort(a+1,a+1+n,cmp); nn=n;
	for(int i=1;i<=n-1;i++)//每次檫最大
	{
		a[1]=a[1]*a[2]+1;
		a[2]=a[nn]; nn--;
		sort(a+1,a+1+nn,cmp);
	}
	
	sort(b+1,b+1+n); nn=n;
	for(int i=1;i<=n-1;i++)//每次擦最小
	{
		b[1]=b[1]*b[2]+1;
		b[2]=b[nn]; nn--;
		sort(b+1,b+1+nn);
	}
	printf("%d",b[1]-a[1]);
	return 0;
}

 

#10006. 「一本通 1.1 練習 2」數列分段

題目

題目大意

給定的一個長度爲N的正整數數列A_i。

將其分成連續的若干段,使每段和不超過M,問最少能將其分成多少段。

對於20%的數據,有n<=10;

對於40%的數據,有n<=1000;

對於100%的數據,有n<=10^5,m<=10^9大於所有數的最大值。

題目分析

好水。

不懂就看代碼ba。

代碼

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

int main()
{
	int n,m; scanf("%d%d",&n,&m);
	int s=0,ans=0;
	for(int i=1;i<=n;i++)
	{
		int x; scanf("%d",&x); s+=x;
		if(s>m) { ans++; s=x; }//超過了
	}
	if(s) ans++;
	printf("%d",ans);
	return 0;
}

 

#10007. 「一本通 1.1 練習 3」線段

題目

題目大意

有n條線段,選取其中k條線段使這k條線段沒有重合部分,問k最大爲多少。

對於20%的數據,n<=10;

對於50%的數據,n<=10^3;

對於70%的數據,n<=10^5;

對於100%的數據,n<=10^6,0<=ai<bi<10^6。

題目分析

迴歸例題1、2???

一段時間改成了一條線段。

一樣要需要沒有重合。

報告完畢。

代碼

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

struct node{int a,b;}a[1000010];
int cmp(node x,node y) { return x.b<y.b; }

int main()
{
	int n; scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].a,&a[i].b);
	sort(a+1,a+1+n,cmp);
	int ans=1,end=a[1].b;
	for(int i=2;i<=n;i++)
	{
		if(a[i].a>=end)
		{
			ans++; end=a[i].b;
		}
	}
	printf("%d",ans);
	return 0;
}

 

#10008. 「一本通 1.1 練習 4」家庭作業

題目

題目大意

每個作業完成時間都是一天,在規定的時間內交上來的話纔有學分。

找到一個完成作業的順序獲得最大學分。

對於20%的數據,n<=10^3;

對於40%的數據,n<=10^4;

對於60%的數據,n<=10^5;

對於100%的數據,n<=10^6,作業的完成期限均小於7*10^5

題目分析

迴歸例題5。

只要加一個小小小優化就好了。

而且這個優化很容易懂。

kk判斷i和i之前的時間是否被填滿,若已經填滿了就不要去找了。

代碼

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

bool f[700010],kk[700010];
struct node{int time,money;}a[1000010];
int cmp(node x,node y) { return x.money>y.money; }

int main()
{
	int n; scanf("%d",&n);
	memset(f,false,sizeof(f));
	memset(kk,false,sizeof(kk));
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].time,&a[i].money);
	sort(a+1,a+1+n,cmp);
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		bool k=false;
		for(int j=a[i].time;j>=1;j--)
		{
			if(kk[j]) break;
			if(!f[j]) { f[j]=true; k=true; }
			if(k) break;
		}
		if(k) ans+=a[i].money;
		else kk[a[i].time]=true;
	}
	printf("%d",ans);
	return 0;
}

 

#10009. 「一本通 1.1 練習 5」釣魚

題目

題目大意

有n個釣魚湖,從左到右編號爲1,2,…,n。希望利用H個小時釣到更多的魚。

從1出發,向右走,可選擇在湖邊停留一定的時間釣魚,最後在某一個湖邊結束釣魚。

從第i個湖到第i+1個湖需要走5*T_i分鐘,測出在第i個湖停留,第一個5分鐘可以釣到F_i條魚,以後再釣5分鐘,釣到的魚量減少D_i,若減少後的魚量小於0,則魚量爲0。

沒有其他因素影響釣到期望數量的魚。求出最多能釣魚的數量。

對於100%的數據,2<=n<=100,1<=h<=20。

題目分析

釣個魚怎麼這麼多事。

枚舉最遠去到的魚塘的位置,範圍內的魚塘任你挑,當然是釣最多的啊。

很好懂的吧。好暴力啊。

我果然還是太辣雞了,如果魚的數量是負的就不要釣了,傻嗎還釣。

我纔不會告訴你我小測的時候就錯在這。

代碼

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

bool f=false;
int n,h,s,t[110],ans=0;
struct node{int a,b;}a[110],b[110];
int cmp(node x,node y) { return x.a>y.a; }

int main()
{
	scanf("%d%d",&n,&h);
	for(int i=1;i<=n;i++) scanf("%d",&a[i].a);
	for(int i=1;i<=n;i++) scanf("%d",&a[i].b);
	h*=12; t[1]=0; s=n;//12個五分鐘
	for(int i=2;i<=n;i++)
	{
		int x; scanf("%d",&x);
		t[i]=t[i-1]+x;//x個五分鐘
		if(!f&&t[i]>=h) f=true,s=i-1;//s表示最遠能去到的魚塘 
	}
	for(int ed=1;ed<=s;ed++)
	{
		for(int i=1;i<=ed;i++) b[i]=a[i];
		int tt=h-t[ed],kk=0;
		while(tt--)//實在是很暴力了 
		{
			sort(b+1,b+1+ed,cmp);
			if(b[1].a<=0) break;
			kk+=b[1].a; b[1].a-=b[1].b;
		}
		ans=max(ans,kk);
	}
	printf("%d",ans);
	return 0;
}

 

#10010. 「一本通 1.1 練習 6」糖果傳遞

這道題已經盡我的洪荒之力寫的詳細了!!!(個人覺得很明白了昂)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章