贪心算法和二分查找算法
一、贪心算法
简单介绍一下贪心算法:这种算法就是在每一次选择中,总是做出当前看来最好的选择,而不从整体的最优考虑,选择只是某种意义上局部的最优解。举几个例子:最短路径、最小生成树就需要用贪心算法来求解。
1.基本思想
贪心算法一步步进行,每次都对当前的局部最优解判断:若添加入部分解后仍是可行解就加入;否则舍弃该局部解,寻找下一个局部最优解,直到将所有数据全部枚举完成或可以确定达到目标。
2.基本的解题步骤
一:建立数学模型分析问题 二:选定合适的贪心选择标准 三:根据贪心选择标准完成算法
3.实际应用
比如航电的2037这道题,便是最简单,最直接的贪心算法的应用:
题目是这样的:
题目:今年暑假不AC
Problem Description
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%...”
确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
Input
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。
Output
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
Sample Input
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
Sample Output
5
解题思路:
我们拿到这道题时,我们想的是要去看更多的节目,也就是在前面看更多的短时间节目,后来才能看更多的节目,所以这里我们就需要对两种时间进行排序,为了能够看到最多的节目,首先将开始时间和结束时间存到两个数组里,然后将结束时间从小到大排序,排序时将对应的开始时间也进行排序,这样可以保证接下来的每次的结束时间都是最早的,赋值节目数初值为1,从第一个节目开始,将该节目的结束时间和下一个节目的开始时间进行对比,如果节目的结束时间大于或者等于下一个节目的开始时间则可以安排进去,节目数加1,最终得到的节目数即能安排的最多节目数。
这就是从局部的最优解来考虑,如果是按照普通思维,也就是从整体来考虑的话,开始时间和结束时间的不同也意味着两种不同的变量,只是单从结束和开始时间是无法对问题进行求解的。
解题代码:
#include<stdio.h>
int main (void)
{
int n, t, i, j, count, k;
int a[200], b[200];
while(scanf("%d", &n)&&n)
{
count=1;
for(i=0; i<n; i++)
{
scanf("%d%d", &a[i], &b[i]);
}
for(i=1; i<n; i++)
{
for(j=0; j<n-i; j++)
{
if(b[j]>b[j+1])
{
t=b[j];
b[j]=b[j+1];
b[j+1]=t;
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
k=b[0];
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if(k<=a[j])
{
i=j;
k=b[j];
count++;
}
}
}
printf("%d\n", count);
}
return 0;
}
这道题只是贪心算法的简单应用,贪心算法还能应用到多种题类中,我现在能理解的也只有活动选择类问题,还有很多的类型我还没有掌握,比如找零,背包,小船渡河等,今后也会持续学习。
二: 二分查找法
简介:
如果给我们一串数据,然后让我们寻找其中的某个数,可能首先想到的是利用循环从第一个元素开始试,直到找出来这个数或者没有找到循环结束。但是这样的方法耗费时间长,所以就要用到二分查找法。
比如这一题:
给定一串数字(从1道10),然后输入要查找的数字,如果此数能在数列中找到的话
则输出该数字在第几位数字,否则输出“无该数字”
input
5
output
5
input
11
output
无该数字!
解题思路:
将我们要查找的值通过与中间元素比较,分为三种情况: 第一种情况:目标值与中间元素相等,查找结束; 第二种情况:目标值比中间元素大,则把后半部分的中间元素与目标值比较; 第二种情况:目标值比中间元素小,则把前半部分的中间元素与目标值比较; 这三步一直循环,直到查找结束。
代码实现:
#include <stdio.h>
int Bin_Search(int *num,int cnt,int target)
{
int first = 0,last = cnt-1,mid;
int counter = 0;
while(first <= last)
{
counter ++;
mid = (first + last) / 2;
if(num[mid] > target)
{
last = mid-1;
}
else if(num[mid] < target)
{
first = mid+1;
}
else
{
printf("查找次数:%d\n",counter);
return 1;
}
}
printf("查找次数:%d\n",counter);
return 0;
}
int main(void)
{
int flag = 0,target;
int num[10] = {1,2,3,4,5,6,7,8,10};
while(1)
{
printf("请输入您要查找的数字:\n");
scanf("%d",&target);
flag = Bin_Search(num,10,target);
if(flag) printf("已经找到该数字!!\n");
else printf("无该数字!!\n");
}
return 0;
}
|