D - Data Center-2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest

本文讨论了使用贪心算法解决机器任务分配问题,包括如何通过排序和选择不同容量的机器来满足任务需求,同时确保分配效率最大化。算法分为两种情况处理,一种是机器数量不足以满足所有低电压任务,另一种则是反之。通过逐步比较和优化,最终确定所需机器数量和类型,以实现任务的有效完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

贪心

先把高低电压各存在一个数组并排序

题目思路很简单。  就是先 贪心得到 最少的机器数num

然后分2种情况

1:num<= 所有低电压机器数量  此时 先假设全部低电压被选了

然后  根据 if  (当前cap之和是否>= m)  来贪心  ( 不断比较"已选"的最小cap的低电压机器 和大cap的高电压机器)  (都已排序)

2: num>总低电压机器数量(a)

此时 先假设全部低电压机器被选了,并且再选num-a步 较大cap的高电压(已排序)

 然后也是  根据 if  (当前cap之和是否>= m)  来贪心  ( 不断比较"已选"的最小cap的低电压机器 和”未选“的较大cap的高电压机器) (都已排序)



代码写得比较长。。。乱


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue> 
#include <set>
#include <vector>
using namespace std;
struct ren
{
	__int64 ca;
	int v;
	__int64 code; 
};

ren tm[100000*2+5];				//所有机器 //升序
ren nm1[100000*2+5];		//保存低电压code  升序
ren nm2[100000*2+5];		//保存高电压code  升序
__int64 ans[100000*2+5];    //记录选过了的code
__int64 vis[100000*2+5];   //标记要删除的code
int cmp(ren a,ren b)
{
	if (a.ca!=b.ca)
		return a.ca>b.ca; 
	else
	{
		return a.v>b.v;
	}
}
int main()
{
	
	__int64 i,j;
	__int64 n,m,cop_m;
	scanf("%I64d %I64d",&n,&m);
	cop_m=m;
	for (i=1;i<=n;i++)
	{
		scanf("%I64d %d",&tm[i].ca,&tm[i].v); 
		tm[i].code=i;
	}
	
	sort(tm+1,tm+1+n,cmp); 
	__int64 ok1=0;
	__int64 ok3=0;	
	__int64 ok2=0;
	__int64	star=0;
	for (i=1;i<=n;i++)
	{
		if (tm[i].v==1)
		{
			nm1[++ok1].ca=tm[i].ca;
			nm1[ok1].code=tm[i].code;
			
		}
		else
		{ 
			nm2[++ok2].ca=tm[i].ca;
			nm2[ok2].code=tm[i].code;
			
		}
	} 
	__int64 num=0;  
	for (i=1;i<=n;i++)
	{
		
		if (m<=0) break; 
		m-=tm[i].ca;
		num++;  
	} 
	m=cop_m;
	__int64 max_low=0;          //最小低电压机器数
	if (num<=ok1)			// 最小机器数小于等于 低电压机器数
	{
		
		for(i=1;i<=num;i++)
		{
			star+=nm1[i].ca;
			ans[++ok3]=nm1[i].code;
			
		}
		
		
		max_low=num;   //此情况下 假设先全部选低电压  
		__int64 it;
		for ( i=num,j=1;j<=ok2 &&i>=1;)
			
		{
			if (star>=m) break;
			star=star-nm1[i].ca+nm2[j].ca;
			//	sort(ans+1,ans+1+ok3);
			//	it= lower_bound(ans+1,ans+1+ok3,nm1[i].code)-&ans[1]+1;
			//	ans[it]=0;
			vis[nm1[i].code]=-1;   //删除该编号
			ans[++ok3]=nm2[j].code;
			max_low--;
			i--;
			j++;  
		}
		
		
		
		
	}
	else						// 最小机器数大于 低电压机器数
	{
		 
		for(i=1;i<=ok1;i++)    //此情况下 假设先全部选低电压 再从最大cap值的高电压机器凑够num个
		{
			star+=nm1[i].ca;
			ans[++ok3]=nm1[i].code;
			
		}
		
		for(i=1;i<=num-ok1;i++)
		{
			star+=nm2[i].ca;
			ans[++ok3]=nm2[i].code;
			
		}
		
		
		max_low=ok1;          //最小低电压机器数为ok1个(全部低电压机器)
		__int64 it;
		for ( i=ok1,j=num-ok1+1;j<=ok2 &&i>=1;)
			
		{
			if (star>=m) break;
			
			star=star-nm1[i].ca+nm2[j].ca;
			//	sort(ans+1,ans+1+ok3);
			//	it= lower_bound(ans+1,ans+1+ok3,nm1[i].code)-&ans[1]+1;
			//	ans[it]=0;
			vis[nm1[i].code]=-1;         //删除该编号
			ans[++ok3]=nm2[j].code;
			max_low--;
			i--;
			j++;  
			
		}
		
		
	} 
	int line=0;
	printf("%I64d %I64d\n",num,max_low);
	for (i=1;i<=ok3;i++)
	{
		
		if (	vis[ans[i]] !=-1 )
		{
			if (line!=0) printf(" ");
			printf("%I64d",ans[i]);
			line=1;
		}
		
	}
	
	printf("\n");
	return 0; 
	
} 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值