题目链接:https://vjudge.net/problem/HDU-3045

Picnic Cows

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3491    Accepted Submission(s): 1124

Problem Description
It’s summer vocation now. After tedious milking, cows are tired and wish to take a holiday. So Farmer Carolina considers having a picnic beside the river. But there is a problem, not all the cows consider it’s a good idea! Some cows like to swim in West Lake, some prefer to have a dinner in Shangri-la ,and others want to do something different. But in order to manage expediently, Carolina coerces all cows to have a picnic!
Farmer Carolina takes her N (1<N≤400000) cows to the destination, but she finds every cow’s degree of interest in this activity is so different that they all loss their interests. So she has to group them to different teams to make sure that every cow can go to a satisfied team. Considering about the security, she demands that there must be no less than T(1<T≤N)cows in every team. As every cow has its own interest degree of this picnic, we measure this interest degree’s unit as “Moo~”. Cows in the same team should reduce their Moo~ to the one who has the lowest Moo~ in this team——It’s not a democratical action! So Carolina wishes to minimize the TOTAL reduced Moo~s and groups N cows into several teams.
For example, Carolina has 7 cows to picnic and their Moo~ are ‘8 5 6 2 1 7 6’ and at least 3 cows in every team. So the best solution is that cow No.2,4,5 in a team (reduce (2-1)+(5-1) Moo~)and cow No.1,3,6,7 in a team (reduce ((7-6)+(8-6)) Moo~),the answer is 8.
 
Input
The input contains multiple cases.
For each test case, the first line has two integer N, T indicates the number of cows and amount of Safe-base line.
Following n numbers, describe the Moo~ of N cows , 1st is cow 1 , 2nd is cow 2, and so on.
 
Output
One line for each test case, containing one integer means the minimum of the TOTAL reduced Moo~s to group N cows to several teams.
 
Sample Input
7 3
8 5 6 2 1 7 6
 
Sample Output
8
 
Source
 
Recommend
gaojie
 

题意:

有n头牛去野营,烧烤,吃什么,牛肉?细思极恐。不扯了。将这n头牛分成若干组,且每一组至少要有T头。每头牛都有一个值,一个组的值是这个组内,所有牛的值减去最小值的差之和。而总和为所有组的值之和,问:怎样分配,才能使得总和最小?

题解:

1.可得一个结论:尽量把值相近的牛分到同一组。所以首先需要根据值的大小对牛进行排序。然后就是一个区间划分的问题了。

2.由于n<=4e5,O(n^2)DP枚举是会超时的,所以需要利用斜率进行优化。

3.由于题目规定了每一组的个数必须大于等于T,因此需要特别处理:

1) dp值从下标为T开始求,因为1~T-1都不能构成一组,其DP没有意义。

2) 在求得dp[i]之后,不能直接把 i 放进队列中,因为 i 不一定能为i+1、i+2……等作状态转移,因为必须要满足一组个数大于等于T的要求。然而,这个还不是最重要的,如果直接把 i 放进队列,那么因为斜率优化所进行的操作:把认为比 i 劣且在队列里的元素出队了,而这些元素又是往后的状态所必须知道的。因此就出现了错误。

3) 根据2) 我们需要限定:在队列里的元素,必须都是往后状态所能够转移的,相比之下只是优劣问题而已。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXM = 1e5+;
const int MAXN = 4e5+; LL val[MAXN], sum[MAXN], dp[MAXN];
int q[MAXN], head, tail; LL getUp(int j, int k)
{
return (dp[j]-sum[j]) - (dp[k]-sum[k]);
} LL getDown(int j, int k)
{
return j-k;
} LL getDp(int i, int j)
{
return dp[j]+(sum[i]-sum[j])-1LL*(i-j)*val[i];
} int main()
{
int T, n;
while(scanf("%d%d", &n,&T)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%lld", &val[i]);
sort(val+, val++n);
reverse(val+, val++n); //降序 sum[] = ;
for(int i = ; i<=n; i++)
sum[i] = sum[i-]+val[i]; // O(n^2)的写法:
// for(int i = T; i<=n; i++)
// {
// dp[i] = sum[i]-i*val[i];
// for(int j = T; j<=i-T; j++)
// dp[i] = min(dp[i], dp[j]+sum[i]-sum[j]-1LL*(i-j)*val[i]);
// } head = tail = ;
dp[] = ;
q[tail++] = ;
for(int i = T; i<=n; i++) //从T开始,因为前面的都无效
{
while(head+<tail && getUp(q[head+],q[head])<=
-1LL*getDown(q[head+],q[head])*val[i]) head++;
dp[i] = getDp(i, q[head]); int j = i-T+; //加入对从下一个开始有效的状态,而i-T+1对i+1、i+2……有效
if(j<T) continue; //只有j>=T, j才有效,能转移状态
while(head+<tail && 1LL*getUp(j, q[tail-])*getDown(q[tail-],q[tail-])<=
1LL*getUp(q[tail-],q[tail-])*getDown(j, q[tail-])) tail--;
q[tail++] = j;
}
printf("%I64d\n", dp[n]);
}
}

错误写法:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXM = 1e5+;
const int MAXN = 1e3+; int val[MAXN], sum[MAXN], dp[MAXN];
int q[MAXN], head, tail; int getUp(int i, int j)
{
return dp[i] - dp[j];
} int getDown(int i, int j)
{
return sum[i] - sum[j];
} int getDp(int i, int j)
{
return dp[j] + (sum[i]-sum[j]+)*val[i];
} int main()
{
int T, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
sum[] = ;
for(int i = ; i<=n; i++)
scanf("%d%d", &sum[i],&val[i]), sum[i] += sum[i-]; dp[] = ;
head = tail = ;
q[tail++] = ;
for(int i = ; i<=n; i++)
{
while(head+<tail && getUp(q[head+],q[head])<=getDown(q[head+],q[head])*val[i]) head++;
dp[i] = getDp(i, q[head]);
/*
直接把i加进去为何错误?因为i的存在不能为i+1的转移作贡献,本来放着没什么关系的,
关键是i加进去的时候,还可能会把前面的去掉,这样就有可能把能为i+1转移的去掉了。
所以,加进队列的应该是那些能为往后所有状态转移的。
*/
while(head+<tail && getUp(i, q[tail-])*getDown(q[tail-],q[tail-])<=
getUp(q[tail-],q[tail-])*getDown(i, q[tail-])) tail--;
q[tail++] = i;
}
printf("%d\n", dp[n]);
}
}

HDU3045 Picnic Cows —— 斜率优化DP的更多相关文章

  1. hdu 3045 Picnic Cows(斜率优化DP)

    题目链接:hdu 3045 Picnic Cows 题意: 有n个奶牛分别有对应的兴趣值,现在对奶牛分组,每组成员不少于t, 在每组中所有的成员兴趣值要减少到一致,问总共最少需要减少的兴趣值是多少. ...

  2. HDU 3045 Picnic Cows(斜率优化DP)

    Picnic Cows Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  3. POJ2018 Best Cow Fences —— 斜率优化DP

    题目链接:https://vjudge.net/problem/POJ-2018 Best Cow Fences Time Limit: 1000MS   Memory Limit: 30000K T ...

  4. 【转】斜率优化DP和四边形不等式优化DP整理

    (自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...

  5. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  6. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

  7. [BZOJ3156]防御准备(斜率优化DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3156 分析: 简单的斜率优化DP

  8. 【BZOJ-1096】仓库建设 斜率优化DP

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Stat ...

  9. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

随机推荐

  1. __new__ 与 __init__的区别

    原文地址:http://www.cnblogs.com/ifantastic/p/3175735.html 单例模式 class Singleton(object): def __new__(cls, ...

  2. 回顾基础知识,类,fbv,cbv

    一 类中绑定方法的传参,不需要self class Foo(object): def __init__(self,name): self.name = name def foo(self,x): se ...

  3. 作诗(bzoj 2821)

    Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗 之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次 ...

  4. 在线预览Word,Excel

    今天在项目中遇到了在线预览word的需求,经过查阅资料与测试发现可以解决问题,特做记录: 方式: http://view.officeapps.live.com/op/view.aspx?src= s ...

  5. [转发]Android 系统稳定性 - ANR(三)

    文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之. 编写者:李文栋 http://rayleeya.iteye.com/blog/1956056 1. ...

  6. keepalived学习

    HA集群 keepalived heartbeat corosync cman 功能实现 vrrp协议在Linux主机上以守护进程方式, 能够根据配置文件自动生成ipvs规则 对各RS健康状态检测 组 ...

  7. 漫话最小割 part1

    codeforces 724D [n个城市每个城市有一个特产的产出,一个特产的最大需求.当i<j时,城市i可以运最多C个特产到j.求所有城市可以满足最大的需求和] [如果直接最大流建图显然会T. ...

  8. Java并发编程,Condition的await和signal等待通知机制

    Condition简介 Object类是Java中所有类的父类, 在线程间实现通信的往往会应用到Object的几个方法: wait(),wait(long timeout),wait(long tim ...

  9. c++单元测试指南:使用google test

    Reference:http://www.codeproject.com/Articles/811934/Cplusplus-unit-test-start-guide-how-to-set-up-G ...

  10. PostgreSQL触发器的使用

    原文: https://www.yiibai.com/postgresql/postgresql-trigger.html -------------------------------------- ...