• BZOJ 1029 JSOI2007 建筑抢修 贪心+堆


    题目大意:n个建筑须要抢修。第i个建筑须要T1时间抢修。必须在T2时间之前抢修完成。求最多能抢修多少建筑

    首先我们对T2排序 然后依次修理 可是这样贪心显然是不对的 比方说这组数据:

    5
    10 10
    10 20
    2 21
    2 21
    2 21

    贪心仅仅能修理前两个。而实际上最多能够修理4个

    于是我们考虑修正贪心算法

    比方说这组数据,当我们枚举到3的时候。尽管已经无法修理很多其它了,可是我们能够取消修理建筑1而改修理3。这样尽管不能更新ans 可是能够为后面的建筑节省时间

    所以做法就非常明白了

    我们维护一个大根堆 每修理一栋建筑 我们就把这栋建筑的T1值增加堆 若当前无法修理 我们推断堆顶是否比这栋建筑的T1大 假设大 取消修理堆顶。改为修理当前建筑

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define M 150100
    using namespace std;
    struct construction{
    	int T1,T2;
    	bool operator < (const construction &x) const
    	{
    		return T2 < x.T2;
    	}
    }buildings[M];
    int n,ans,now,heap[M],top;
    void Insert(int x)
    {
    	heap[++top]=x;
    	int t=top;
    	while(t>1&&heap[t]>heap[t>>1])
    		swap(heap[t],heap[t>>1]),t>>=1;
    }
    void Pop()
    {
    	heap[1]=heap[top--];
    	int t=2;
    	while(t<=top)
    	{
    		if(t<top&&heap[t+1]>heap[t])
    			++t;
    		if(heap[t]>heap[t>>1])
    			swap(heap[t],heap[t>>1]),t<<=1;
    		else
    			break;
    	}
    }
    int main()
    {
    	int i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    		scanf("%d%d",&buildings[i].T1,&buildings[i].T2);
    	sort(buildings+1,buildings+n+1);
    	for(i=1;i<=n;i++)
    	{
    		if(now+buildings[i].T1<=buildings[i].T2)
    		{
    			now+=buildings[i].T1;
    			++ans;
    			Insert(buildings[i].T1);
    		}
    		else
    		{
    			if(!top)
    				continue;
    			int temp=heap[1];
    			if( temp>buildings[i].T1 )
    				now=now+buildings[i].T1-temp,Pop(),Insert(buildings[i].T1);
    		}
    	}
    	cout<<ans<<endl;
    }
    


  • 相关阅读:
    手机端页面自适应解决方案
    每日一算法之拓扑排序
    C++顺序容器类总结
    c++ 运算符优先级
    CUDA获取显卡数据
    第一个CUDA程序
    C++有关类的符号总结
    shell编程的一些例子5
    shell编程的一些例子4
    shell编程的一些例子3
  • 原文地址:https://www.cnblogs.com/llguanli/p/6752447.html
Copyright © 2020-2023  润新知