贪心算法例题(持续更新)

组个最小数

题目大意:给定0~9十个数字各自的数目,要求所有的给定数字必须全部用上,并使组成的数字最小

难度:容易

输入样例:2 2 0 0 0 3 0 0 1 0
输出样例:10015558

#include <iostream>
using namespace std;

//先从非零的数中选一个最小的当做首位,然后后面就可以从所有的数中从小到大的选 
int main()
{
	int N=10,a[10]={0},i=0;
	while(N--)
	{
		cin>>a[i];
		i++;
	}
	for(int i=1;i<=9;i++)
	{
		if(a[i]>0)
		{
			cout<<i;
			a[i]--;
			break;
		}
	}
	for(int i=0;i<10;i++)
	{
		if(a[i]>0)//这个判断可以省去 
		{
			for(int j=0;j<a[i];j++)
			{
				cout<<i;
			}
		}
	}
	cout<<"ok"<<endl;
}
从商店里坑最多的钱

题目大意:给定多个coupon,多个商品,都为整数(正、负、零),我们最终得到的钱是coupon与商品的乘积和,求最大

难度:较易

输入样例:
4
1 2 4 -1
4
7 6 -2 -3
输出样例:
43

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

//先利用sort函数从小到大排序,然后从头处理负数,接着从尾部开始倒着处理正数 

const int maxnum=100010;
int main()
{
	int coupon[maxnum],good[maxnum],ans=0,k=0,z=0;
	int m,n;
	cin>>m;
	int m1=m;//注意记录,不然会为零
	for(int i=0;m>0;m--,i++)
	{
		cin>>coupon[i];
	}
	cin>>n;
	int n1=n;//注意记录
	for(int i=0;n>0;n--,i++)
	{
		cin>>good[i];
	}
	sort(coupon,coupon+m1);
	sort(good,good+n1);
	while(coupon[k]<0&&good[z]<0&&k<m1&&z<n1)
	{
		ans+=coupon[k]*good[z];
		k++;
		z++;
	}
	k=m1-1;
	z=n1-1;
	while(coupon[k]>0&&good[z]>0&&k>=0&&z>=0)
	{
		ans+=coupon[k]*good[z];
		k--;
		z--;
	}
	cout<<ans<<endl;
	cout<<"ok"<<endl;
} 
swap最小的次数复原序列

题目大意:给定一个序列(有n个数,n<100000),从0到n-1,但是顺序打乱,请用最少的swap次数将这个序列复原,但是限制是每次的swap中的参数都要含有0这个元素

难度:中等

测试案例:
5 0 1 2 3 4
output
0

5 1 2 3 4 0
output
4

9 0 2 1 4 3 6 5 8 7
output
12

思路:输入的时候获取0的位置,比如是num[5],那么就把0与5交换(5归位),直到0归位,如果此时还是乱序,那么将0与最近的一个没有归位的元素调换,然后重复上一步。最后0归位的时候应该就是顺序。

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

const int maxnum=100010;
int main()
{
	int m,num[maxnum],i=0,zero,count=0,miss=0;//zero记录的是0的位置,随时更新,count记录的是调换的次数,miss记录的是没有归位的元素的个数 
	cin>>m;
	int m1=m;//注意记录 
	while(m--)
	{
		cin>>num[i];
		if(num[i]==0)
		{
			zero=i;
		}
		if(num[i]!=i)
		{
			miss++;
		}
		i++;
	}
	while(true)
	{
		if(num[0]==0)
		{
			if(miss==0) break;//退出总循环 
			for(int i=0;i<m1;i++)
			{
				if(num[i]!=i)
				{
					swap(num[0],num[i]);
					zero=i;
					count++;
					miss++;
					break;//在这层循环中一旦找到就马上退出 
				}
			}
		}
		else
		{
			for(int i=0;i<m1;i++)
			{
				if(num[i]==zero)
				{
					swap(num[i],num[zero]);
					count++;
					if(i==0)
					{
						miss-=2;
					}
					else 
					{
						miss--;
					}
					zero=i;
					break;//在这层循环中一旦找到就马上交换退出 
				}
			}
		}
	}
	cout<<count<<endl;
	cout<<"ok"<<endl;
}
拼接产生最小的字符串

题目大意:给出n个字符串片段(都是数字),然后要求把它们拼接起来,求最小的情况,开头如果是0的话就要去掉

难度:容易

测试案例
输入
5
32 321 3214 0229 87
输出
22932132143287

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

const int maxnum=10010;

bool cmp(string a,string b)
{
	return a+b<b+a;//如果a+b<b+a,那么就把a排在b的前面 
}

//此题的关键是要进行拼接尝试,不能说a<b就把a排在b的前面了,所以比较函数需要另外设计 
int main()
{
	int m;
	string str[maxnum],ans="";
	cin>>m;
	for(int i=0;i<m;i++)
	{
		cin>>str[i];
	}
	sort(str,str+m,cmp);
	for(int i=0;i<m;i++)
	{
		ans+=str[i];
	}
	while(ans.size()&&ans[0]=='0')//注意这里是字符
	{
		ans.erase(ans.begin());//这里参照stl博客,有多种写法
	}
	if(ans.size()==0) cout<<0<<endl;
	else
	{
		cout<<ans<<endl;
	}
	cout<<endl;
	cout<<"ok"<<endl;
} 
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值