zoukankan      html  css  js  c++  java
  • 台州 OJ 3847 Mowing the Lawn 线性DP 单调队列

    描述

     

    After winning the annual town competition for best lawn a year ago, Farmer John has grown lazy; he has not mowed the lawn since then and thus his lawn has become unruly. However, the competition is once again coming soon, and FJ would like to get his lawn into tiptop shape so that he can claim the title.

    Unfortunately, FJ has realized that his lawn is so unkempt that he will need to get some of his N (1 <= N <= 100,000) cows, who are lined up in a row and conveniently numbered 1..N, to help him. Some cows are more efficient than others at mowing the lawn; cow i has efficiency E_i (0 <= E_i <= 1,000,000,000).

    FJ has noticed that cows near each other in line often know each other well; he has also discovered that if he chooses more than K (1 <= K <= N) consecutive (adjacent) cows to help him, they will ignore the lawn and start a party instead. Thus, FJ needs you to
    assist him: determine the largest total cow efficiency FJ can obtain without choosing more than K consecutive cows.

    输入

     

    * Line 1: Two space-separated integers: N and K

    * Lines 2..N+1: Line i+1 contains the single integer: E_i
     

    输出

     

    * Line 1: A single integer that is the best total efficiency FJ can obtain.

     
     
    题目的意思是给 n 个整数,从这 n 个整数中选出一些,并且连续部分的长度不能超过 k,求这些整数最大的和是多少。
    转载一篇博客:http://blog.csdn.net/magical_qting/article/details/47205093   和这道题很相似
    转换成上面链接里的那道题目,就是求,长度为 k+1 的连续部分中必有一个断点。
    dp[i] 表示,第 i 个数字不选时,前 i-1 个数字中去掉的数字的和的最小值。
    dp[i] = min(dp[x]) + num[i]  (i-k-1 <= x <= i-1)
    求出去掉的数字的和的最小值后,用所有数字的和减去去掉的数字的和,就是答案了。
    PS:台州的编译器有点不同,用 long long 貌似会出错,改成 64 位 int 就过了。
     
    代码:
    #include <iostream>
    #include <cstring>
    #define LL __int64
    using namespace std;
    
    const int MAX = 100005;
    
    LL dp[MAX];		//不放 i 时,前 i 个数字组成的序列,去掉的数字的最小和 
    LL que[MAX];		//单调队列 
    int pos[MAX];		//队列中元素对应的下标 
    int front, rear;
    int n, m;
    
    int main(){
    	
    //	freopen("input.txt", "r", stdin);
    //	freopen("output.txt", "w", stdout);
    	
    	scanf("%d%d", &n, &m);
    	LL num;
    	LL sum = 0;
    	LL ans;
    	memset(dp, 0x3f, sizeof(dp));
    	dp[0] = 0;	//去掉第一个  
    	front = 0;  rear = 1;	//初始化单调队列 
    	que[rear] = 0;
    	pos[rear] = 0;
    	for(int i=1; i<=n; i++){
    		if(rear != front && pos[front+1] < i-m-1){	//如果前面的数字过期了 
    			front++;
    		}
    		scanf("%I64d", &num);
    		sum += num;
    		//计算 dp[i]
    		dp[i] = que[front+1] + num;
    		//将 dp[i] 放入队列
    		while(rear != front && que[rear] > dp[i]){
    			rear--;
    		} 
    		que[++rear] = dp[i];
    		pos[rear] = i; 
    		if(i == n-m){
    			ans = dp[i];
    		}
    		if(i >= n-m){
    			ans = min(ans, dp[i]);
    		}
    	}
    	//最后 m+1 个数字中,在哪个地方断开 
    	
    	printf("%I64d
    ", sum-ans);
    	
    	return 0;
    }
    

      

     
     
     
     
     
  • 相关阅读:
    临时表 Vs 表变量
    發行項帶篩選的合併複製問題之訂閱者更新導致部份數據丟失
    生成创建表的脚本V2.0(PowerShell版)
    PowerShell应用之事务复制
    PowerShell应用之批量还原数据库(支持完整,差异,事务日志)
    一个有意思的问题:如何根据一年中的第几周,查询出它周六和周日对应的日期
    千万级数据的分页
    了解SQL Server触发器及触发器中的事务
    修改表主键字段数据类型(up_ModifyPrimaryColumn)
    The specified CGI application encountered an error and the server terminated the processThe specified CGI application encountered an error and the server terminated the process
  • 原文地址:https://www.cnblogs.com/lighter-blog/p/7397162.html
Copyright © 2011-2022 走看看