五一假期简单贪心十练之后五练

POJ 2393

题意:任务规定,一个酸奶制造厂,在n个星期内,分别要向外提供y[i]t的酸奶。已知这个制造厂第i周制造每单位酸奶的费用为c[i],储存室储存每1单位酸奶1星期的费用为s。

            问要完成这个任务的最小费用是多少。

贪心策略:对于每星期都要使得该星期的费用最小即c[i]=(c[i],c[i-1]+s)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    int n,s;
    int c[10005];
    int y[10005];
    while(cin>>n>>s)
    {
        for(int i=0;i<n;i++)
        {
            cin>>c[i]>>y[i];
        }
        long long ans=0;
        for(int i=1;i<n;i++)
            c[i]=min(c[i-1]+s,c[i]);
        for(int i=0;i<n;i++)
        {
            ans+=c[i]*y[i];
        }
        cout<<ans<<endl;
    }

    return 0;

}

POJ 1017

题意:一个工厂制造的产品形状都是长方体盒子,它们的高度都是 h,长和宽都相等,一共有六个型号,分别为1*1, 2*2, 3*3, 4*4, 5*5, 6*6。

            这些产品通常使用一个 6*6*h 的长方体箱子包装然后邮寄给客户。因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的箱子数量BoxNum。

贪心策略:。。。纯模拟。。累死了。。。 这道题没啥好说的。。我还因为敲这道题加上模拟过程花去太多时间没在第一时间见到我姐姐姐夫TVT,是CF那道TAXI的升级版

                    画6*6的格子自己来里面填充。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    int a[7];
    while(cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6])
    {
        if(a[1]==0&&a[2]==0&&a[3]==0&&a[4]==0&&a[5]==0&&a[6]==0)
            return 0;
        int ans=0;
        while(a[6]-->0)
        {
            ans++;//6*6个单独放
        }
        while(a[5]-->0)
        {
            ans++;//5*5的每放置一个
            a[1]-=11;//1*1的自动减少11个
        }
        while(a[4]-->0)
        {
            ans++;
            if(a[2]>0)
            {
                a[2]-=5;//2*2的还有那么最多可以放5个
             if(a[2]<0)
                {
                    a[1]+=a[2]*4;//1*1的最多可以放这么多个不过注意a[2]是负数了。
                }
            }
            else
            {
                a[1]-=20;//没有2*2只能放1*1最多放20个
            }
        }

        ans+=a[3]/4;//3*3的四个可以放满一个,看有多少个则加
        int ans3=a[3]%4;//3*3的放不满的话
        if(ans3==1)
        {
            ans++;
            if(a[2]>0)
            {
                a[2]-=5;
                a[1]-=7;
                if(a[2]<0)
                {
                    a[1]+=a[2]*4;
                }
            }
            else
            {
                a[1]-=27;
            }

        }
        else  if(ans3==2)
        {
          ans++;
          if(a[2]>0)
          {
              a[2]-=3;
              a[1]-=6;
                if(a[2]<0)
            {
                a[1]+=a[2]*4;
            }
          }
          else
          {
              a[1]-=18;
          }

        }
        else if(ans3==3)
        {
            ans++;
            if(a[2]>0)
            {
                a[2]-=1;
                a[1]-=5;
            }
            else
            {
                a[1]-=9;
            }
        }
        if(a[2]>0)
        {
            ans+=a[2]/9;
            if(a[2]%9!=0)
            {
                ans++;
                a[1]-=36-((a[2]%9)*4);

            }
        }
        if(a[1]>0)
        {
            ans+=a[1]/36;
            if(a[1]%36!=0)
            {
                ans++;
            }
        }
        cout<<ans<<endl;
    }

    return 0;

}
POJ 3040

题意:一个人每周得到c美分的报酬,而FJ有面值为V的硬币数B个,求如何分配可以让支付的周数最大,即损失最少。

贪心策略:按照V的升序排列,大于等于C美分的,就当亏本了全部给他累计数量,然后小于C的,找到最大的去匹配,如果还不行,就拿大面值的跟小面值的去匹配。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{

int v;
int b;

}a[25];
bool cmp(node a,node b)
{
    return a.v<b.v;
}
int x[25];

int main()
{
    int n,c;
    while(cin>>n>>c)
    {
        int ans=0;
        for(int i=0;i<n;i++)
        {
            cin>>a[i].v>>a[i].b;
        }
        sort(a,a+n,cmp);
        int t=-1;
        for(int i=n-1;i>=0;i--)
        {
            if(a[i].v>=c)//大于C的直接+
            {
                ans+=a[i].b;
            }
            else
            {
                t=i;//记录小于C的最大所对应的面值去匹配
                break;
            }

        }
        while(1)
        {
            memset(x,0,sizeof(x));
            int r=c;
            int tt;
            for(int i=t;i>=0;i--)
            {
                if(a[i].b==0||r==0)
                    continue;
                tt=r/a[i].v;//剩下的可以用当前最大面值的凑多少张
                tt=min(tt,a[i].b);//是否大于自己有的东西
                x[i]=tt;
                r-=tt*a[i].v;//减去这些价值
            }
            if(r!=0)//如果还不行
            {
                for(int i=0;i<=t;i++)//从小的往回凑
                {
                    if(a[i].v>=r&&(a[i].b-x[i])!=0)
                    {
                        x[i]++;
                        r=0;
                        break;
                    }
                }
                if(r!=0)
                {
                    break;
                }
            }
            int w=99999999999;
            for(int i=0;i<=t;i++)

                if(x[i]!=0)

                    w=min(w,a[i].b/x[i]);
                    ans+=w;


            for(int i=0;i<=t;i++)
            {
                a[i].b-=w*x[i];
            }
        }


        cout<<ans<<endl;
    }


    return 0;
}

POJ 1862

题意:两两碰撞得到新东西,然后最后只会有一个东西,要让这东西的质量最小。。

思路:卖萌。。代码最下方有简单的策略

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;

/*double calc(double a,double b)
{
    double ans;
    ans=2*sqrt(a*b);
    return ans;
}

int main()
{
    int n;
    double a[105];
    while(cin>>n)
    {
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        sort(a,a+n);
        double mina=a[n-1];
        for(int i=n-1;i>=1;i--)
        {
            mina=calc(mina,a[i-1]);

        }
          printf("%.3lf\n",mina);
    }
    return 0;
}*///数学方法

int main()
{

    int n;
    while(cin>>n)
    {
        priority_queue<double> q;
        for(int i=0;i<n;i++)
        {
            double t;
            cin>>t;
            q.push(t);
        }
        while(q.size()!=1)
        {
                double a=q.top();
                q.pop();
                double b=q.top();
                q.pop();
                double c=2*sqrt(a*b);
                q.push(c);
        }
        double ans=q.top();
        printf("%.3lf\n",ans);
    }
    return 0;
}//优先队列

//重量大的多次碰撞可以多次开方

POJ 3262

题意:有n个牛在FJ的花园乱吃。

            所以FJ要赶他们回牛棚。

            每个牛在被赶走之前每秒吃Di个花朵。赶它回去FJ要花的时间是Ti*2。在被赶走的过程中牛就不能乱吃了

贪心策略:一开始看样例以为是按照单位时间内DI的降序排列,每次去赶摧毁量最大的。。然后发现不对。。因为还跟T有关

                    后来卡住了好久看了下DISCUSS,说考虑最简单的情况,那么就考虑只有两只牛A B的情况,那么只有两种方法,其损失率为

                    DA*TB和DB*TA,处理完两头牛,剩下的也可以按照这个局部的思路来考虑,那么其实对于N头牛,则以前面那个关系按照升序排列(化简一下实际上是一个比例问  题),然后就没有然后了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

struct node{
long long  t;
long long d;


}a[100005];

bool cmp(node a,node b)
{
    return a.t*b.d<a.d*b.t;
}

int main()
{
    int n;
    while(cin>>n)
    {
        long long  ans=0;
        for(int i=0;i<n;i++)
        {
            cin>>a[i].t>>a[i].d;
            a[i].t*=2;
        }
        sort(a,a+n,cmp);
        long long  sum=0;
        for(int i=0;i<n;i++)
        {
            ans+=sum*a[i].d;
            sum+=a[i].t;
            //cout<<ans<<"~!~"<<sum<<endl;
        }
        cout<<ans<<endl;
    }

    return 0;

}
//a b 两头牛的情况 要么先a后b 要么先b后a 那么损失就是ta*db和tb*da按照降序排列,n头牛等价于子问题
//便可以求解




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值