zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:开心的金明(贪心+模拟)

    题目传送门(内部题117)


    输入格式

      第一行一个整数$k$,表示需要处理的月份数。
      接下来的$k$行,每行$4$个整数,第$1+i$行分别为:$c_i,d_i,m_i,p_i$
      接下来的$k-1$行,每行三个整数,其中第$1+k+i$行分别为:$e_i,R_i,E_i$。分别表示从第$i$月存到$i+1$月的数据。


    输出格式

      一行,包括一个整数。如果能够满足所有顾客的需求,输出最小成本。如果不能满足顾客需求,输出$-1$。


    样例

    样例输入1:

    2
    10 5 3 6
    15 7 2 8
    2 3 2

    样例输出1:

    170

    样例输入2:

    2
    0 8 0 7
    0 0 0 0
    0 0 0

    样例输出2:

    -1


    数据范围与提示

    样例$1$解释:

      在第一个样品测试用例中,第一个月,你可以购买$12$个单位的原材料,这需要花费$120$元,然后把其中的7个放入下个月的仓库,这需要花费$21$元。然后,你的公司可以生产$5$台电脑并销售,这需要$15$元。在第二个月,贵公司可以生产和销售$7$台,使用仓库中的原材料的电脑,需要$14$元。总成本为$170$元,证明是最优的。

    数据范围:

      对于$10\%$的数据,$k=2$;
      对于$30\%$的数据,$kleqslant 100$;
      对于$50\%$的数据,$kleqslant 1,000$;
      对于$70\%$的数据,$kleqslant 10,000$;
      对于$100\%$的数据,$2leqslant kleqslant 50,000,0leqslant c_i,d_i,m_i,p_ileqslant 10^4,0leqslant eileqslant 10^8,0leqslant R_i,E_ileqslant 10^4$。


    题解

    考虑贪心,最后剩余电脑数为$0$一定最优;购买的原材料数量和出售的电脑数一定相同。

    因为原材料可以无限购买和存储,所以$c[i]=min(c[i],c[i-1]+R[i-1])$。

    那么考虑电脑,也可以用这样的方式处理;开一个$multiset$存储即可。

    剩下的就都是模拟了。

    时间复杂度:$Theta(klogmax(e[i]))$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    #define L(x) x<<1
    #define R(x) x<<1|1
    using namespace std;
    struct rec{int c,d,m,p,e,R,E;}e[50010];
    int n,size,lst;
    multiset<pair<int,int>>s;
    long long ans;
    int main()
    {
    	scanf("%d",&n);e[0].c=0x3f3f3f3f;
    	for(int i=1;i<=n;i++)scanf("%d%d%d%d",&e[i].c,&e[i].d,&e[i].m,&e[i].p);
    	for(int i=1;i<n;i++)scanf("%d%d%d",&e[i].e,&e[i].R,&e[i].E);
    	for(int i=1;i<=n;i++)e[i].c=min(e[i].c,e[i-1].c+e[i-1].R);
    	for(int i=1;i<=n;i++)e[i].m+=e[i].c;
    	for(int i=1;i<=n;i++)
    	{
    		s.insert(make_pair(e[i].m-lst,e[i].p));
    		size+=e[i].p;
    		while(e[i].d)
    		{
    			if(s.empty()){puts("-1");return 0;}
    			pair<int,int> x=*s.begin();
    			s.erase(s.begin());
    			size-=x.second;
    			if(e[i].d<x.second)
    			{
    				ans+=1LL*(x.first+lst)*e[i].d;
    				x.second-=e[i].d;e[i].d=0;
    				size+=x.second;
    				s.insert(x);
    			}
    			else
    			{
    				ans+=1LL*(x.first+lst)*x.second;
    				e[i].d-=x.second;
    			}
    		}
    		while(e[i].e<size)
    		{
    			pair<int,int> x=*--s.end();
    			s.erase(--s.end());
    			size-=x.second;
    			if(size<e[i].e)
    			{
    				x.second=e[i].e-size;
    				s.insert(x);
    				size+=x.second;
    			}
    		}
    		lst+=e[i].E;
    	}
    	printf("%lld",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    JAVA常用运算符
    JAVA基本语义简介
    JAVA常用关键字
    记事本写JAVA程序
    JAVA开发环境搭建
    PROTEL DXP原理图编译 常见错误与处理方法
    关于光耦的认识
    十六进制转十进制函数_C编程
    Protues记录文档_1
    SR触发器和JK触发器
  • 原文地址:https://www.cnblogs.com/wzc521/p/11790652.html
Copyright © 2011-2022 走看看