问题一 : 背包问题 但是是允许并不将一个物品全部装满
/*
贪心问题 :这个问题与 01 背包问题的最大区别就是 并不是0 1
*/
#include<iostream>
#include<vector>
#include<stdio.h>
#include<cstdio>
#include<algorithm>
using namespace std;
struct JavaBean
{
double weight;
double cost;
};
const int MAXN =1000;
//def 一个 结构体 实现
JavaBean arr[MAXN];
bool Compare( JavaBean x, JavaBean y)
{
return (x.weight/x.cost>y.weight/y.cost);
}
int main()
{
int m,n;
while( scanf("%d%d",&m,&n)!=EOF)
{
if(m==-1&&n==-1)
{
break;
}
for( int i=0; i<n; i++)
{
scanf("%lf%lf",&arr[i].weight,&arr[i].cost);
}
sort(arr,arr+n,Compare);
// 按照性价比降序排序即可
double answear=0;
for( int i=0;i<n;i++){
if(m>=arr[i].cost){
m-=arr[i].cost;
answear+=arr[i].weight;
}
else {
answear+=arr[i].weight*(m/arr[i].cost);
break;
}
}
printf("%.3f\n",answear);
}//while
return 0;
}
区间最优问题:
目标: 尽可能的观看多的完整的节目 , 输入的数据包含多个测试的实例, 每一个测试实例的第一行只有一个数据, 之后的每一行都包含两个数字分别代表开始时间, 结束时间。
/*
区间最优问题
*/
#include<iostream>
#include<vector>
#include<stdio.h>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Program
{
int startTime;
int endTime;
};
const int MAXN =100;
Program arr[MAXN];
bool Compare(Program x, Program y) //升序方式排列
{
return x.endTime<y.endTime;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
{
break;
}
for( int i =0; i<n; i++)
{
scanf("%d%d",&arr[i].startTime,&arr[i].endTime);
}
sort(arr,arr+n,Compare);
int currentTime=0;
int answer=0;
for(int i =0; i<n; i++)
{
if(currentTime<=arr[i].startTime)// 就算是有结束的时间的相同也可以
{
currentTime=arr[i].endTime;
answer++;
}
}
printf("%d\n",answer);
}
return 0;
}
下面看一个比较复杂的例子 :
一个人需要在 不同岛屿中架桥, 为了简化问题将岛屿的坐标为一维的,例如[ 1 4 ] 另外的一个岛屿是 [ 6 8 ] 现在有m桥使得架桥最多, 并且桥在左右的两端的坐标为 x y , y-x为 length , 因此存在一个interval 的最大最小值。
/*
*/
#include<iostream>
#include<vector>
#include<stdio.h>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int MAXN =100;
struct Island
{
long long left; // 左端点
long long right; // 右端点
};
struct Bridge
{
int length;
int index; // 第几个
};
struct Interval{
long long minimum;
long long maxmum;
long long index;
bool operator<(Interval x) const { // 重载一下 < 符号就可以了
return maxmum>x.maxmum;
}
};// 定义区间
bool IntervalCompare(Interval x , Interval y){ // 最小的距离来
if(x.minimum==y.minimum){
return x.maxmum<y.maxmum;
}
else {
return x.minimum<y.minimum;
}
} //sort 使用时候的比较函数
bool BridgeCompare(Bridge x ,Bridge y){
return x.length<y.length; //升序
}
Island island[MAXN];
Bridge bridge[MAXN];
Interval interval[MAXN];
long long answer[MAXN];
bool Solve( int n, int m ){
priority_queue<Interval> myQueue;
int position=0;
int number=0;
for( int i=0;i<m;i++){
while(myQueue.top().maxmum<bridge[i].length && !myQueue.empty()){
myQueue.pop();
}
while(position <n-1 &&
interval[position].minimum <=bridge[i].length&&
interval[position].maxmum>=bridge[i].length
){
myQueue.push(interval[position]);
// 因为要选择maxmum最小的所以还不能动
position++;
// position的条件是用于 控制 interval的个数的
}
if(!myQueue.empty()){
Interval current = myQueue.top();
myQueue.pop();
answer[current.index]=bridge[i].index;
number++;
}
}
return number==n-1;
}
int main(){
int n ,m;
while(scanf("%d%d",&n,&m)!=EOF){
memset(island, 0,sizeof(island));
memset(bridge, 0,sizeof(bridge));
memset(interval, 0,sizeof(interval));
memset(answer, 0, sizeof(answer));
for( int i= 0; i<n;i++){
scanf("%11d%11d",&island[i].left,&island[i].right);
}
for( int i =0;i<n-1;i++){
scanf("11%d",&bridge[i].length);
bridge[i].index=i+1;
}
for( int i =0;i<n-1;i++){
interval[i].minimum= island[i+1].left-island[i].right;
interval[i].maxmum= island[i+1].right- island[i].left;
interval[i].index=i;
}
sort(interval, interval+n-1,IntervalCompare);
//先做一个 interval 的升序排列
sort(bridge, bridge+n-1,BridgeCompare);
// 做一个bridge的长度的升序
if(Solve(n,m)){
printf("ok!");
}
}
}
这个代码 因为是 首先 bridge是按照 升序的方式递增的, 同时 position只是初始化了一次 因此,并不回溯。所以保证了bridge[]并不重复.