2021牛客暑期多校训练营6 - F - Hamburger Steak( 构造 )

题目链接:点击进入
题目

在这里插入图片描述
在这里插入图片描述

题意

n 个汉堡,m 个锅,每个汉堡都有做熟所需时间 t i t_i ti,一个汉堡可以在一个锅上做,也可以分两次在两个锅上做,一个锅每刻只能做一个汉堡,一个汉堡每刻只能在一个锅上。求一个汉堡放置方案,使所有汉堡做好所需时间最少( 这个所需时间,应该是所有汉堡都做完的那一刻时间 )

思路

我们求出锅的最大时间限制是多少,应该是 max ( n 个汉堡中的最长时间 ,n 个汉堡平均时间 ),我们知道一个锅最大时间是多少,剩下的就是贪心的放置汉堡,如果锅里放得下一整个汉堡,就放置,如果放不下,那就尽量放,这个汉堡剩下的那部分时间放到另一个新的锅里,重复过程,直到所有汉堡都放置结束。这样放置汉堡,一个汉堡的时间不会存在交集。因为 ti <= max,就算一个汉堡放到两个锅里,因为前半部分在锅后程,后半部分在锅前程,因此不会存在交集 ( 这里放置类似栈 )。

代码
//#pragma GCC optimize(3)//O3
//#pragma GCC optimize(2)//O2
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define best 131 
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define lowbit(x) x & -x
#define inf 0x3f3f3f3f
#define int long long
//#define double long double
//#define rep(i,x,y) for(register int i = x; i <= y;++i)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const int maxn=1e6+10;
const int mod=998244353;
const double eps=1e-9;
const int N=5e3+10;
/*--------------------------------------------*/
inline int read()
{
    int k = 0, f = 1 ;
    char c = getchar() ;
    while(!isdigit(c)){if(c == '-') f = -1 ;c = getchar() ;}
    while(isdigit(c)) k = (k << 1) + (k << 3) + c - 48 ,c = getchar() ;
    return k * f ;
}
/*--------------------------------------------*/

int n,m,t[maxn],sum,maxx,maxt;
struct node
{
	int pos;
	int x;
}p[maxn];

struct Node
{
	int l;
	int r;
	int pos;
};

bool cmp(node e,node f)
{
	return e.x>f.x;
}
vector<Node>v[maxn];

signed main() 
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>t[i],sum+=t[i],maxt=max(maxt,t[i]);
	for(int i=1;i<=n;i++) p[i].pos=i,p[i].x=t[i];
	if(sum%m==0) maxx=sum/m;
	else maxx=sum/m+1;
	maxx=max(maxx,maxt);
	//sort(p+1,p+n+1,cmp);
	int pos1=m,pos2=1;
	while(pos1>=1&&pos2<=n)
	{
		if(p[pos2].x==maxx)
		{
			v[p[pos2].pos].push_back({0,maxx,pos1});
			pos2++;
			pos1--;
		}
		else
		{
			int tmp=0;
			while(pos2<=n&&tmp+p[pos2].x<=maxx)
			{
				tmp+=p[pos2].x;
				v[p[pos2].pos].push_back({tmp-p[pos2].x,tmp,pos1});
				pos2++;
			}
			if(pos2<=n&&tmp!=maxx)
			{
				p[pos2].x-=(maxx-tmp);
				v[p[pos2].pos].push_back({tmp,maxx,pos1});
			}
			pos1--;
			
		}
	}
	for(int i=1;i<=n;i++)
	{
		cout<<v[i].size()<<" ";
		for(int j=v[i].size()-1;j>=0;j--)
			cout<<v[i][j].pos<<" "<<v[i][j].l<<" "<<v[i][j].r<<" ";
		cout<<endl;
	}
    return 0;
} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值