#2020寒假集训#贪心入门(Greed)代码笔记

简述

  • 在对问题求解时,总是做出在当前看来是最好的选择
  • 不从整体最优上加以考虑,只做出在某种意义上的局部最优解
  • 不是对所有问题都能得到整体最优解,关键是贪心策略的选择
  • 选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关

例题

Part One 活动选择问题 HDU-2037-今年暑假不AC

#2020寒假集训#贪心入门(Greed)代码笔记_第1张图片

#include
#include
#include
using namespace std;
const int maxn=1e2+10;
const int inf=0x3f3f3f3f;
int n,endflag,sum;
struct putin
{
	int st;
	int ed;
}put[maxn];
bool cmp(putin a,putin b)
{
	return a.ed<b.ed;
}
int main()
{
	while(~scanf("%d",&n)&&n)
	{
		for(int i=1;i<=n;++i) scanf("%d %d",&put[i].st,&put[i].ed);
		sort(put+1,put+n+1,cmp);
		endflag=0,sum=0;
		for(int i=1;i<=n;++i)
		{
			if(put[i].st>=endflag)
			{
				endflag=put[i].ed;
				sum++;
			}
		}
		printf("%d\n",sum);
	}
	return 0;
}

Part Two 钱币找零问题

#2020寒假集训#贪心入门(Greed)代码笔记_第2张图片

Part Three 多机调度问题

#2020寒假集训#贪心入门(Greed)代码笔记_第3张图片

Part Four 小船过河问题 POJ-1700-Crossing River

#2020寒假集训#贪心入门(Greed)代码笔记_第4张图片
#2020寒假集训#贪心入门(Greed)代码笔记_第5张图片

#include
#include
#include
using namespace std;
const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int T,n,sum,put[maxn];
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		memset(put,0,sizeof(put));
		scanf("%d",&n);
		for(int i=1;i<=n;++i) scanf("%d",&put[i]);
		sort(put+1,put+n+1);
		sum=0;
		while(n>=4)
		{
			sum+=min(put[1]+2*put[2]+put[n],2*put[1]+put[n-1]+put[n]);
			n-=2;
		}
		if(n==1) sum+=put[1];
		else if(n==2) sum+=put[2];
		else if(n==3) sum+=put[3]+put[1]+put[2];
		printf("%d\n",sum);
	}
	return 0;
}

Part Five 区间覆盖问题 POJ-1328-Radar Installation

#2020寒假集训#贪心入门(Greed)代码笔记_第6张图片

#2020寒假集训#贪心入门(Greed)代码笔记_第7张图片

#include
#include
#include
#include
using namespace std;
const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int T,d,n,x,y,ans;
struct island
{
	double left;
	double right;
}put[maxn];
bool cmp(island a,island b)
{
	if(a.left!=b.left) return a.left<b.left;
	else return a.right<b.right;
}
int main()
{
	int Case=0;
	while(~scanf("%d %d",&n,&d),n+d)
	{
		int flag=1;
		for(int i=1;i<=n;++i)
		{
			scanf("%d %d",&x,&y);
			if(y>d) flag=0;
			put[i].left=(double)x-sqrt(d*d-y*y);
			put[i].right=(double)x+sqrt(d*d-y*y);
		}
		if(!flag)
		{
			printf("Case %d: -1\n",++Case);
			continue;
		}
		sort(put+1,put+n+1,cmp);
		double R=put[1].right;
		ans=1;
		for(int i=2;i<=n;++i)
		{
			if(put[i].left<=R) R=min(R,put[i].right);//用取min来合并相交和包含的情况 
			else ans++,R=put[i].right;
		}
		printf("Case %d: %d\n",++Case,ans);
	}
	return 0;
}

Part Six 其他问题 HDU-1009-FatMouse’ Trade

#2020寒假集训#贪心入门(Greed)代码笔记_第8张图片

#include
#include
#include
using namespace std;
const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int m,n;
double sum;
struct change
{
	double javebeans;
	double fatmouse;
	double value;
}put[maxn];
bool cmp(change a,change b)
{
	return a.value>b.value;
}
int main()
{
	while(~scanf("%d %d",&m,&n))
	{
		if(m==-1&&n==-1) break;
		for(int i=1;i<=n;++i)
		{
			scanf("%lf %lf",&put[i].javebeans,&put[i].fatmouse);
			put[i].value=put[i].javebeans/put[i].fatmouse;
		}
		sort(put+1,put+n+1,cmp);
		sum=0;
		for(int i=1;i<=n;++i)
		{
			if(m>put[i].fatmouse)
			{
				sum+=put[i].javebeans;
				m-=put[i].fatmouse;
			}
			else
			{
				sum+=put[i].value*m;
				break;
			}
		}
		printf("%.3f\n",sum);
	}
	return 0;
}

Part Six 其他问题 HDU-1050-Moving Tables

#2020寒假集训#贪心入门(Greed)代码笔记_第9张图片
#2020寒假集训#贪心入门(Greed)代码笔记_第10张图片

#include
#include
#include
using namespace std;
const int maxn=4e2+10;
const int inf=0x3f3f3f3f;
int T,n,cnt[maxn],Max;
struct putin
{
	int st;
	int ed;
}put[maxn];
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		memset(cnt,0,sizeof(cnt));
		scanf("%d",&n);
		for(int i=1;i<=n;++i)
		{
			scanf("%d %d",&put[i].st,&put[i].ed);
			if(put[i].st>put[i].ed) swap(put[i].st,put[i].ed);
			if(put[i].st%2==0) put[i].st--;
			if(put[i].ed%2==1) put[i].ed++; 
		}
		for(int i=1;i<=n;++i)
		{
			for(int j=put[i].st;j<=put[i].ed;++j) cnt[j]++;
		}
		Max=0;
		for(int i=1;i<=400;++i) Max=max(Max,cnt[i]);
		printf("%d\n",Max*10);
	}
	return 0;
}

Part Six 其他问题 POJ-1017-Packets

#2020寒假集训#贪心入门(Greed)代码笔记_第11张图片
#2020寒假集训#贪心入门(Greed)代码笔记_第12张图片

#include
#include
#include
using namespace std;
const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int T,n,put1,put2,put3,put4,put5,put6;
int main()
{
	while(~scanf("%d %d %d %d %d %d",&put1,&put2,&put3,&put4,&put5,&put6))
	{
		if(put1==0&&put2==0&&put3==0&&put4==0&&put5==0&&put6==0) break;
		int last1=0,last2=0,last3=0,sum=0;
		sum=(put3+3)/4+put4+put5+put6;
		
		if(put3%4==0) last2=put4*5;
		else if(put3%4==1) last2=put4*5+5;
		else if(put3%4==2) last2=put4*5+3;
		else if(put3%4==3) last2=put4*5+1;
		if(put2>last2) sum+=(put2-last2+8)/9;
		
		last1=sum*36-put6*36-put5*25-put4*16-put3*9-put2*4;
		if(put1>last1) sum+=(put1-last1+35)/36;
		
		printf("%d\n",sum);
	}
	return 0;
}
/*
	注意求 n 个物品,一个箱子能装 m 个,需要多少个箱子的时候
	如果直接整除,如 n==4 && m==4
	n 为 3 需要 1 个,n 为 4 需要 1 个,n 为 5 需要 2 个,很难分类讨论
	所以可用 (n+m-1)/m来求得
	如 n==4 && m==4,n 为 3 需要 (3+3)/4 个
	n 为 4 需要 (4+3)/4 个,n 为 5 需要 (5+3)/4 个,
*/

Part Six 其他问题 HDU-1051-Wooden Sticks

#2020寒假集训#贪心入门(Greed)代码笔记_第13张图片

#include
#include
#include
using namespace std;
const int maxn=5e3+10;
const int inf=0x3f3f3f3f;
int T,n;
bool used[maxn];
struct putin
{
	int length;
	int weight;
}put[maxn];
bool cmp(putin a,putin b)
{
	if(a.length!=b.length) return a.length<b.length;
	else return a.weight<b.weight;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		memset(used,false,sizeof(used));
		for(int i=1;i<=n;++i) scanf("%d %d",&put[i].length,&put[i].weight);
		sort(put+1,put+n+1,cmp);
		int ans=0;
		for(int i=1;i<=n;++i)
		{
			if(used[i]==true) continue;
			int before=put[i].weight;
			used[i]=true;
			ans++;
			for(int j=i+1;j<=n;++j)
			{
				if(!used[j]&&put[j].weight>=before)
				{
					used[j]=true;
					before=put[j].weight;
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

Part Six 其他问题 HDU-1338-Game Prediction

#2020寒假集训#贪心入门(Greed)代码笔记_第14张图片

#include
#include
#include
#include
using namespace std;
const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int T,m,n,x,y,lose,put[maxn],other[maxn];
bool have[maxn],used[maxn];
int main()
{
	int Case=0;
	while(~scanf("%d %d",&m,&n)&&m+n)
	{
		memset(have,false,sizeof(have));
		memset(used,false,sizeof(used));
		for(int i=1;i<=n;++i) scanf("%d",&put[i]),have[put[i]]=true;
		sort(put+1,put+n+1);
		int key=0;
		for(int i=1;i<=n*m;++i) if(!have[i]) other[++key]=i;
		int lose=0;
		for(int i=n;i>=1;--i)
		{
			for(int j=key;j>=1;--j)
			{
				if(!used[other[j]]&&other[j]>put[i])
				{
					used[other[j]]=true;
					lose++;
					break;
				}
			}
		}
		printf("Case %d: %d\n",++Case,n-lose);
	}
	return 0;
}

Part Six 其他问题 HDU-1789-Doing Homework again

#2020寒假集训#贪心入门(Greed)代码笔记_第15张图片

#include
#include
#include
using namespace std;
const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int T,n,ans;
bool used[maxn];
struct homework
{
	int ddl;
	int goal;
}put[maxn];
bool cmp(homework a,homework b)
{
	if(a.goal!=b.goal) return a.goal>b.goal;
	else return a.ddl<b.ddl;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		memset(used,false,sizeof(used));
		scanf("%d",&n);
		for(int i=1;i<=n;++i) scanf("%d",&put[i].ddl);
		for(int i=1;i<=n;++i) scanf("%d",&put[i].goal);
		sort(put+1,put+n+1,cmp);
		ans=0;
		for(int i=1;i<=n;++i)
		{
			if(!used[put[i].ddl]) used[put[i].ddl]=true;
			else
			{
				int day=put[i].ddl;
				while(day)
				{
					if(!used[day])
					{
						used[day]=true;
						break;
					}
					else day--;
				}
				if(day==0) ans+=put[i].goal;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

Part Six 其他问题 HDU-6709-Fishing Master

#2020寒假集训#贪心入门(Greed)代码笔记_第16张图片

#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
int n,k,put,num,cnt;
long long sum;
using namespace std;
int main()
{
	int T;
	scanf("%d",&T);
	priority_queue<int> Q;
	//以备取出的都是当前炖鱼耗时最长的鱼 
	while(T--)
	{
		scanf("%d %d",&n,&k);
		cnt=1,sum=k;//初始化总时长,先钓上第一条鱼,才能进入炖的步骤 
		for(int i=1;i<=n;++i)
		{
			/*
				每次输入都会有入队,即后续要等的炖鱼的时间 
				能用来钓鱼就不要浪费时间,多出来的时间才入队 
				如果炖鱼时间本就小于钓鱼时间,入队的就是本身啦 
			*/ 
			scanf("%d",&put);
			//输入的是被炖的时间 
			num=put/k;//炖这条鱼不浪费时间地能钓多少条鱼就钓都钓上来
			cnt+=num;//统计利用炖鱼时间能钓多少条鱼 
			sum+=num*k;//统计当前的钓鱼总耗时 
			Q.push(put%k);
			/*
				炖鱼时间小于钓鱼时间的当做炖起来快些的鱼  
				现在的想法是炖它的时候拼命钓鱼
				能不傻愣着就不傻愣着
				实在不行也要尽量等炖起来快的鱼之时傻愣着
			*/
		}
		//Q.size()是总鱼数,num是能利用起来钓到的鱼
		//钓多了不要紧,时间 k 不用来钓鱼也是要用来等炖的 
		while(cnt<Q.size()) sum+=k,Q.pop();
		//没钓完,只能用不足 k 的炖时来钓一条鱼
		//先节省等着炖久的(优先队列队首)让鱼炖过头
		while(!Q.empty()) sum+=Q.top(),Q.pop();
		//钓完了鱼,剩下的一条接一条炖 
		printf("%lld\n",sum);
	}
	return 0;
}

Part Six 其他问题 ZOJ-2883-Shopaholic

#2020寒假集训#贪心入门(Greed)代码笔记_第17张图片

#include
#include
#include
using namespace std;
const int maxn=2e4+10;
const int inf=0x3f3f3f3f;
int T,n,ans,put[maxn];
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		memset(put,0,sizeof(put));
		scanf("%d",&n);
		for(int i=1;i<=n;++i) scanf("%d",&put[i]);
		sort(put+1,put+n+1);
		ans=0;
		for(int i=n;i>=1;i-=3) ans+=put[i-2];
		printf("%d\n",ans);
	}
	return 0;
}

Part Six 其他问题 HDU-3979-Monster

#2020寒假集训#贪心入门(Greed)代码笔记_第18张图片

#include
#include
#include
#include
using namespace std;
const int maxn=1e4+10;
const int inf=0x3f3f3f3f;
int T,m,n;
long long sum,ans;
struct monster
{
	int HP;
	int ATK;
	int cnt;
	double value;
}put[maxn];
bool cmp(monster a,monster b)
{
	return a.value>b.value;
}
int main()
{
	scanf("%d",&T);
	for(int Case=1;Case<=T;++Case)
	{
		scanf("%d %d",&n,&m);
		sum=0;
		for(int i=1;i<=n;++i)
		{
			scanf("%d %d",&put[i].HP,&put[i].ATK);
			put[i].cnt=(put[i].HP+m-1)/m;
			put[i].value=1.0*put[i].ATK/put[i].cnt;
			sum+=(long long)put[i].ATK;
		}
		sort(put+1,put+n+1,cmp);
		ans=0;
		for(int i=1;i<=n;++i)
		{
			while(put[i].HP>0)
			{
				ans+=sum;
				put[i].HP-=m;
			}
			sum-=(long long)put[i].ATK;
		}
		printf("Case #%d: %lld\n",Case,ans);
	}
	return 0;
}

And So On ……

总结Summary

#2020寒假集训#贪心入门(Greed)代码笔记_第19张图片

你可能感兴趣的:(2020寒假集训)