贪心算法实例&随笔

问题一 : 背包问题 但是是允许并不将一个物品全部装满

/*
贪心问题  :这个问题与 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[]并不重复.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值