序:
我不是大牛,也只是个初学者,写这些也只是为了回顾一下自己所学的知识,当然不会的也求教大牛了,大家对我的要求不要太高,希望大牛多多指点。
正文:
一.算法思路:尽可能的最优解。
—不能能保证最后的解为最优解;
—不能用来求最大或最小解;
—只能用来求满足某些约束条件的可行解的范围。
二.题型:
(1)背包问题:有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。
要求尽可能让装入背包中的物品总价值最大,但不能超过总容量
等对背包问题多种要求详细理解后再以专题形式总结。
(2)活动时间安排问题:设有N个活动时间集合,每个活动都要使用同一个资源,而且同一时间内只能有一个活动使用,每个活动都有一个使用活动的开始si和结束时间fi,即他的使用区间为(si,fi),现在要求你分配活动占用时间表,即哪些活动占用,哪些不占用,使得他们不冲突,要求是尽可能多的使参加的活动最大化,即所占时间区间最大化
此类问题按终点升序排列 (代码中对(si fi)已经按fi的升序赋了初值)所以在未排好序的时候要先排一下序。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> using namespace std; void greedychoose(int len,int *s,int *f,bool *flag) { flag[0]=true; //*flag <=> flag[]; int j=0; for(int i=1;i<len;i++) { if(s[i]>=f[j]) { flag[i]=true; j=i; } } } int main() { int s[11]={1,3,0,5,3,5,6,8,8,2,12}; int f[11]={4,5,6,7,8,9,10,11,12,13,14}; bool mark[11]={0}; //定义一个标记型数组 greedychoose(11,s,f,mark); for(int i=1;i<11;i++) if(mark[i]) cout<<i<<endl; return 0; } // 3 7 10
(3)线段覆盖问题:在一维空间中告诉你N条线段的起始坐标与终止坐标(si fi),要求求出这些线段一共覆盖了多大的长度
此类问题按起始升序排列 (代码中对(si fi)已经按si的升序赋了初值)所以在未排好序的时候也要先排一下序。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
using namespace std;
int main()
{
int s[11]={2,3,4,5,6,7,8,9,10,11};
int f[11]={3,5,7,6,9,8,12,10,13,15};
int total=f[0]-s[0]; //附初值
for(int i=1,j=0;i<10;i++)
{
if(s[i]>=f[i])
{
total+=(f[i]-s[i]);
j=i;
}
else
{
if(f[i]<=f[j])
continue;
else
{
total+=f[i]-f[j];
j=i;
}
}
}
cout<<total<<endl;
return 0;
}
(4)数字组合问题:设有N个正整数,现在需要你设计一个程序,使他们连接在一起成为最大的数字,例3个整数 12,345,678 很明显是67834512为最大,首先这道题是要数字首位的值谁的大,如果单纯的去比较在N非常大时就会存在超时现象。我们可以用一种比较的方式(eg.a b 两个数先写成ab ba 的形式去比较ab 与ba 的大小 代码实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
bool compare(int num1,int num2) { int N1=0,N2=0; int midnum1,midnum2; while(midnum1) { ++N1; midnum/=10; } while(midnum2) { ++N2; midnum2/=10; } int a=num1*pow(10,N2)+num2; int b=num2*pow(10,N1)+num1; return (a>b)? true:flase; }
(5)找零钱的问题:题目大意如下,对于人民币的面值有1元 5元 10元 20元 50元 100元,下面要求设计一个程序,输入找零的钱,输出找钱方案中最少张数的方案,比如123元,最少是1张100的,1张20的,3张1元的,一共5张!
解析:这样的题目运用的贪心策略是每次选择最大的钱,如果最后超过了,再选择第二大的面值,以此类推,一直到最后与找的钱相等,这种情况大家再熟悉不过了,下面看主要实现代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
for(int i=0;i<6;) { if(moneynum+moneyspecies[i]>total) //moneyspecies[i] 代表面值; { i++; continue; } moneynum+=moneyspecies[i]; ++moneyindex[i]; //moneyindex[i]代表每种面值的数量 ++num; if(moneynum==total) break; }
目前也只能整理这么多,就是按自己不熟悉的写的,也没什么值得借鉴的地方,希望大家不要见怪!