zoukankan      html  css  js  c++  java
  • 牛客-H.施魔法(动态规划优化)

    题意:牛可乐有n个元素(编号1...n),第i个元素的能量值为ai。牛可乐可以选择至少k个元素来释放一次魔法,魔法消耗的魔力是这些元素能量值的极差.
    形式化地,若所用元素编号集合为S,则消耗的魔力为这个集合中的最大值减最小值。

    牛可乐要求每个元素必须被使用恰好一次。牛可乐想知道他最少需要多少魔力才能用完所有元素,请你告诉他。
    (链接)[https://ac.nowcoder.com/acm/contest/3003/H]

    分析:贪心地思考,要使每次使用的魔力尽量小,必须是一段连续元素的区间,即要从小到大排序,然后,我们再使用动态规划进行转移,f[i]表示用掉前i个元素的最小花费,当我们计算第i个元素的时候,
    它肯定是作为最小元素被减去的,然后最大元素是[1,i - k + 1]之间的,我们表示为j,同时还要加上f[j - 1],即用掉前j - 1个元素的最小值,那么状态转移方程就是f[i] = min(f[i], f[j - 1] - a[j] + a[i]) j∈[1, i - k + 1]。
    //对于时间复杂度为0(n^2)的DP问题,我们可以采用一些优化,可以利用之前前缀的最小值进行优化,这样,代码的时间复杂度就会降到o(n)。

    时间复杂度o(n^2)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    using LL = long long;
    const int N = 3e5 + 7;
    
    int a[N];
    //用掉前i个元素的最小代价
    int f[N];
    
    
    int main()
    {
    	int n, k;
    	scanf("%d%d", &n, &k);
    
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d", &a[i]);
    	}
    
    	sort(a + 1, a + 1 + n);
    
    	for (int i = 1; i <= n; ++i) f[i] = 2e9;
    
    	for (int i = k; i <= n; ++i)
    	{
    		for (int j = 1; j <= i - k + 1; ++j)
    			f[i] = min(f[i], f[j - 1] - a[j] + a[i]);
    	}
    
    	cout << f[n] << endl;
    
    	return 0;
    }
    
    
    

    时间复杂度o(n)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    using LL = long long;
    const int N = 3e5 + 7;
    
    int a[N];
    //用掉前i个元素的最小代价
    int f[N];
    
    int pre;
    int main()
    {
    	int n, k;
    	scanf("%d%d", &n, &k);
    
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d", &a[i]);
    	}
    
    	sort(a + 1, a + 1 + n);
    	pre = -a[1];
    	for (int i = 1; i <= n; ++i) f[i] = 2e9;
    
    	for (int i = k; i <= n; ++i)
    	{
    		f[i] = pre + a[i];
    		pre = min(pre, f[i - k + 1] - a[i - k + 2]);
    	}
    
    	cout << f[n] << endl;
    
    	return 0;
    }
    
    
    
    
  • 相关阅读:
    Android中Handler与Message的简单实例
    折腾蛋疼的Ubuntu1204LTS的U盘安装
    sgs_intro
    把杀某程序封装成sh
    boost 程序库完全开发_ch4_utility
    VS2005 warning C4819处理办法(提示代码页有不兼容的字符)
    Ubuntu1204LTS下xynxyc编译Emacs24.02
    当VS05调试赋值不对时,小心只是IDE的watch在骗你.....
    很好的boost学习资料
    C++实现Creational Singleton模式
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/12271966.html
Copyright © 2011-2022 走看看