【贪心】POJ_1017 POJ_2376

本文详细解析了POJ1017和POJ2376两个算法题目的解题思路及实现过程。POJ1017通过贪心算法解决最少箱子装载问题;POJ2376则采用贪心策略求解线段最小覆盖问题。

第一次算法实验报告

学生姓名:汪涛    学号:U201014390

POJ 1017

1)  题目描述:

给你一组6种箱子的个数,问最少能够用多少个箱子把给出的一组6种箱子装起来,

输出最少箱子的个数。

2)  解题分析:

由于要使得箱子数最少,所以尽量选择大的箱子来装。

运用贪心。

 

3)  算法设计:

6*6的放满整个盒子,

5*5的还可以放111*1

4*4的还可以放52*2的。

3*3的总个数模4后,也就是说最后一个盒子放几个3*3的。

如果是1,还可以放52*271*1

如果是2,可以放32*261*1

如果是3,可以放12*251*1的。

2*2的模9就是最后一个箱子里放2*2的个数,36-2*2的个数%9)就是可以放1*1

个数。

最后(1*1的个数+35/36就是最后的盒子数。

由于只涉及到常数运算,算法时间复杂度为O(1)

4)  程序代码:

#include "stdio.h"

#include "string.h"

int a[7];

int res[7];

 

int main()

{

    int sum_num ;

 

    while(scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6]))

    {

        sum_num = 0;

        memset(res,0,sizeof(res));

        if( a[1] == 0 && a[2] == 0 && a[3] == 0 && a[4] == 0 && a[5] == 0 && a[6] == 0 )

            break;

        if( a[6] != 0 )

            sum_num += a[6];

        if( a[5] != 0 )

        {

            sum_num += a[5];

            res[1] += 11*a[5];

        }

        if( a[4] != 0 )

        {

            sum_num += a[4];

            res[2] += 5*a[4];

        }

        if(a[3] != 0)

        {

            sum_num += (a[3]+3)/4; //43*3才占用一个6*6

            res[3] += 4-a[3]%4; //剩余多少3*3

            if(res[3] == 1)   //根据3*3的个数推出2*2,1*1的个数

            {

                ++res[2];

                res[1] += 5;

            }

            else if(res[3] == 2)

            {

                res[2] += 3;

                res[1] += 6;

            }

            else if(res[3] == 3)

            {

                res[2] += 5;

                res[1] += 7;

            }

        }

        if(a[2]!=0)

        {

            if(a[2] >= res[2]) //先填剩下的2*2

            {

                a[2] -= res[2];

                res[2] = 0;

            }

            else

            {

                res[2] -= a[2];

                res[1] += res[2]*4; //将剩余2*2转换为1*1的个数

                a[2] = 0;

            }

            if(a[2] > 0) //如果还是不够,则找新的6*6来填充

            {

                sum_num += (a[2]+8)/9; //需要多少个6*6

                res[1] += (9-a[2]%9)*4; //剩下多少个1*1

            }

        }

        if(a[1] != 0)

        {

            if(a[1] >= res[1])

            {

                a[1] -= res[1];

            }

            else

            {

                a[1] = 0;

            }

            sum_num += (a[1]+35)/36; //需要多少个6*6

        }

        printf("%d\n",sum_num);

    }

 

    return 0;

}

5)  实验结果及其分析:

1.

2.

3.结果与想法完全符合

6)实验心得:

由于poj1017这个题目是求一个最优值,所以本次实验采用了贪心的算法思想,用最大的箱子去装物品,剩余空间去容纳小的物品,就是这个贪心的思想。

 

POJ2376

1)  题目描述

农场要做清洁,一个时间段里面至少要有一条牛在工作,要使整个时间段都有牛在工作,求牛的最小数量。

2)  解题分析

可以将需要工作的实践段看作一个线段,每一个牛的工作时间段也看作线段,整个题目就可以转变成求线段的最小覆盖。

3)  算法设计

对牛的工作时间段进行左边由小到大的排序,然后在选择的区域内选择向右延伸最远的,测试完n个牛的数据之后如果不能比t大,则输出-1

4)  程序代码

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

 

typedef struct    //题目的大意就是求线段的最小覆盖

{

    int l , r;    //把牛工作的时间当作线段来处理

}line;

 

line cow[25005];

 

int n , t;

 

int cmp(const line &a , const line &b)

{

    return a.l < b.l;

}

 

int main()

{

    while(scanf("%d%d",&n,&t) != EOF)

    {

        for(int i = 0 ; i < n ; i++)

            scanf("%d%d",&cow[i].l,&cow[i].r);

        sort(cow,cow+n,cmp);

        int count = 0;

        int left = cow[0].l , right = cow[0].r;

        if(left > 1)   //最左边的都比1  那么显然不能覆盖

        {

            printf("-1\n");

            continue;

        }

        int i = 0 , temp_r , ri = 0;

        int flag = 1;

        while(ri < t && i < n)

        {

            int find = 0;

            temp_r = 0;

            while(cow[i].l <= ri+1 && i < n)

            {

                find = 1;

                if(cow[i].r > temp_r)

                    temp_r = cow[i].r;

                i++;

            }

            if(!find)

            {

                flag = 0;

                break;

            }

            ri = temp_r;

            count++;

        }

        if(!flag || ri < t)

            printf("-1\n");

        else

            printf("%d\n",count);

    }

    return 0;

}

5)  实验结果及其分析

1.

2.

3.时间复杂度

计算的复杂度主要在排序O(nlogn)和扫过去的循环O(n)

6)  实验心得

用贪心的思想解决了线段最小覆盖问题。

转载于:https://www.cnblogs.com/zuckerTT/archive/2011/10/10/2205530.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值