ACM总结2--贪心算法

定义

在对问题求解时,总是作出在当前看来是最好的选择。也就是说,不从整体上加以考虑,它所作出的仅仅是在某种意义上的局部最优解

解题步骤

1、从问题的某个初始解出发。
2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。
3、将所有部分解综合起来,得到问题的最终解。
注:若要用贪心算法求解某问题的整体最优解,必须首先证明贪心思想在该问题的应用结果就是最优解!!

例题:

题目1:键盘输入一个高精度的正整数n(<=240位),去掉任意s(s<n)个数字后,将剩下的数字按原左右次序组成一个新的正整数。

给定n和s,请编程输出最小的新正整数。

Sample Input
178543 4
Sample Output
13

思路:每一步总是选择一个使剩下的数最小的数字删除,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字;否则删除第一个递减区间的首字符,这样删一位便形成了一个新的数字串。然后回到串首,按上述规则再删除下一个数字

题目2:设有n个正整数,将它们连成一排组成一个整数,请编程输出其中最大的结果。

例如:n=3时,3个整数13,312,343,连成的最大整数为34331213。

又如:n=4时,4个整数7,13,4,246,连成的最大整数为7424613。

思路:本质上是使用一种规律对已知的数组做一个排序,a+b > b+a 则ab交换

Havel-Hakimi定理

1、可图:一个非负整数组成的序列如果是某个无向图的度序列,则该序列是可图的。
2、度序列:Sequence Degree,若把图G所有顶点的度数排成一个序列,责成该序列为图G的一个序列。该序列可以是非递增序的、可以是非递减序列、可以是任意无序的。
3、Havel-Hakimi定理:给定一个非负整数序列{d1,d2,…dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化。

定理描述:由非负整数组成的有限非递增序列,S={d1,d2,d3…dn},当且仅当S1={d2-1,d3-1…d(d1+1),d(d1+2)…dn}也是可图的,也就是说,序列S1也是由非负整数组成的有限非递增序列,S1是由S的删除第一个元素d1之后的前d1个元素分别减一后得到的序列。
(注,Havel-Hakimi定理 讨论的是在非递增序列下判别是否可图的定理)

例子1:
判断序列S:=6,5,4,3,3,3,2,0 是否可图。

1、 删除首元素6,将除去第一个元素后面的6个元素减一,得到:S1 = 4,3,2,2,2,1,0
2、删除首元素4,将除去第一个元素后面的4个元素减一,得到:S2 = 2,1,1,1,1,0
3、删除首元素2,将除去第一个元素后面的2个元素减一,得到:S3 = 0,0,1,1,0
4、删除首元素0,将除去第一个元素后面的0个元素减一,得到:S4 = 0,1,1,0
5、删除首元素0,将除去第一个元素后面的0个元素减一,得到:S5 = 1,1,0
6、删除首元素1,将除去第一个元素后面的1个元素减一,得到:S6 = 0,0
则最后得到的是非负序列,证明 序列式可图的!

例子2:
判断序列S:=7,6,4,3,3,3,2,1 是否可图。

1、 删除首元素7,将除去第一个元素后面的7个元素减一,得到:S1 = 6,3,2,2,2,1,0
2、删除首元素6,将除去第一个元素后面的6个元素减一,得到:S2 = 2,1,1,1,0,-1
最后得到的是存在负数的序列,证明 序列式不可图的!

主要代码:

bool Havel_Hakimi(int arr[]){  
    for(int i=0; i<n-1; ++i)
		{  
			sort(arr+i,arr+n);// 从第i个元素开始非递增排序 
			if(i+arr[i] >= n) return false;//若第i个元素+arr[i]的值超过原数组长度,那么将溢出。
			for(int j=i+1; j<=i+arr[i] ; ++j)
				{  
				--arr[j];  
					if(arr[j] < 0) return false;  
				}  
		}  
    if(arr[n-1]!=0) return false;  
    return true;  
}

排序

排序是贪心算法常见的预处理操作。编程中常用的方法:
1、自己写(基本功)
2、调用排序函数(方便)
常用排序函数
qsort() C语言
sort() C++

关于sort()函数

头文件:#include
sort(首地址, 尾地址+1, [cmp函数])

这个函数可以传两个或三个参数;
第一个参数是要排序的区间首地址;
第二个参数是区间尾地址的下一地址;
第三个参数不写,则缺省为递增排序。

例子代码:

struct student
{	char name[11];   	int age;  	double score;
}stu[100];

bool cmp1(student x, student y)
{ 	if( fabs(x.score - y.score) > 0.00001 )  //double和flaot比较方法,做差法
        return x.score > y.score;
	if(x.age != y.age) return x.age < y.age;
	return strcmp(x.name,y.name) < 0 ;
}

2019.10.23
plussone

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值