zoukankan      html  css  js  c++  java
  • CodeForces1256 E. Yet Another Division Into Teams

    题意:这里有n个同学在你的大学,第i个同学的编程技巧是ai,作为一个教练,你想把它们分成很多组。每组至少3个人。
    求每组差异的值的总和。如何分组,才能使得差异值的总和最小。

    分析:先排序,肯定是连续数字的组中最大值和最小值差值最小。然后考虑分组的人数的上限,我们最多一组5个人,
    因为假设有6个人,差值为a6 - a1,我们可以分成更多的组数,使得差值减小,比如a3 - a1和a6 - a4,这两组的差值加起来
    等于a6 - a1 + a3 - a4,a3 - a4 < 0,因此答案会变小。

    递推方程为 f[i + j] = min(f[i + j], f[i] + a[i + j].val - a[i + 1].val);

    然后这道题要求我们输出具体的分组方案,求具体的分组方案,我们可以记录每个状态从哪个状态转移过来,然后从最后一个状态反推。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    using LL = long long;
    const int N = 200005;
    //LL a[N];
    LL f[N];//处理前i个人,得到的最小差值
    int p[N];//组编号
    int res[N];
    struct Node
    {
    	LL val;
    	int id;//编号
    	bool operator<(const Node& rhs) const
    	{
    		if (val == rhs.val)
    			return id < rhs.id;
    		return val < rhs.val;
    	}
    }a[N];
    
    int main()
    {
    	memset(f, 0x3f, sizeof f);
    
    	int n;
    	scanf("%d", &n);
    
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%lld", &a[i].val);
    		a[i].id = i;//编号
    	}
    
    	sort(a + 1, a + n + 1);
    
    	f[0] = 0;
    	for (int i = 0; i <= n; ++i)
    	{
    		for (int j = 3; j <= 5 && i + j <= n; ++j)
    		{
    			LL diff = a[i + j].val - a[i + 1].val;
    			if (i + j <= n && f[i + j] > f[i] + diff)
    			{
    				f[i + j] = f[i] + diff;
    				p[i + j] = i;//从i转移过来
    			}
    		}
    	}
    
    	int cur = n;
    	int cnt = 0;//组数
    
    	while (cur != 0)
    	{
    		for (int i = cur; i >= p[cur] + 1; --i)
    		{
    			res[a[i].id] = cnt;
    		}
    		++cnt;
    		cur = p[cur];
    	}
    
    	cout << f[n] << " " << cnt << endl;
    
    	for (int i = 1; i <= n; ++i)
    		printf("%d ", res[i] + 1);
    
    	return 0;
    }
    
    
    
    
    
    
    
    
    
  • 相关阅读:
    oracle数据库的乱码问题解决方案
    @HTML.checkboxFor()用法
    存储过程实现登录(.net)
    .net中大数据的处理
    xml总结
    获取指定日期是当前月的第几周
    JS中正则方法的使用
    获取指定日期的前一天日期
    通过Oracle函数实现.NET String.Format函数的简单版
    ReportViewer实现多语言
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/12828155.html
Copyright © 2011-2022 走看看