题目描述

给出一个长度为 的正整数序列Ci,求一个子序列,使得原序列中任意长度为 的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和最大。

输入

第1行三个数N,m,k。 接下来N行,每行一个字符串表示Ci。

输出

最大和。

样例输入

10 5 3
4 4 4 6 6 6 6 6 4 4

样例输出

30


题解

线性规划与费用流

关于线性规划与费用流的具体讲解参见 bzoj1061 。

这道题和那道差不多,都是给出一大堆限制条件,每个变量在限制条件中的出现是连续的。

所以我们可以按照那道题的思路来做。

原始限制条件是$\begin{cases}0\le x_i\le1\\x_1+x_2+...+x_m\le k\\x_2+x_3+...+x_{m+1}\le k\\...\\x_{n-m+1}+x_{n-m+2}+...+x_n\le k\end{cases}$,

转化为相等关系为$\begin{cases}0\le x_i\le1\\y_i\ge0\\x_1+x_2+...+x_m+y_1=k\\x_2+x_3+...+x_{m+1}+y_2=k\\...\\x_{n-m+1}+x_{n-m+2}+...+x_n+y_{n-m+1}=k\end{cases}$,

添加恒等关系0=0,上下差分并移项得$\begin{cases}x_1+x_2+...+x_m+y_1-k=0\\x_{m+1}-x_1+y_2-y_1=0\\x_{m+2}-x_2+y_3-y_2=0\\...\\x_{n-1}-x_{n-m-1}+y_{n-m}-y_{n-m-1}=0\\x_n-x_{n-m}+y_{n-m+1}-y_{n-m}=0\\-x_{n-m+1}-x_{n-m+2}-...-x_n-y_{n-m+1}+k=0\end{cases}$。

根据这个建图,将这n-m+2个限制条件看作点,那么S->1,容量为k,费用为0;n-m+2->T,容量为k,费用为0;i->i+1,容量为inf,费用为0;对于每个变量xi,判断它系数为+1的位置和系数为-1的位置,+1向-1连边。容量为1,费用为ci。

然后跑最大费用最大流出解,具体地,将费用取相反数,跑最小费用最大流,再反过来即可。

#include <cstdio>
#include <cstring>
#include <queue>
#define N 1500
#define M 30000
#define inf 0x3f3f3f3f
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , cost[M] , next[M] , cnt = 1 , s , t , dis[N] , from[N] , pre[N];
void add(int x , int y , int v , int c)
{
to[++cnt] = y , val[cnt] = v , cost[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
to[++cnt] = x , val[cnt] = 0 , cost[cnt] = -c , next[cnt] = head[y] , head[y] = cnt;
}
bool spfa()
{
int x , i;
memset(from , -1 , sizeof(from));
memset(dis , 0x3f , sizeof(dis));
dis[s] = 0 , q.push(s);
while(!q.empty())
{
x = q.front() , q.pop();
for(i = head[x] ; i ; i = next[i])
if(val[i] && dis[to[i]] > dis[x] + cost[i])
dis[to[i]] = dis[x] + cost[i] , from[to[i]] = x , pre[to[i]] = i , q.push(to[i]);
}
return ~from[t];
}
int mincost()
{
int ans = 0 , i , k;
while(spfa())
{
k = inf;
for(i = t ; i != s ; i = from[i]) k = min(k , val[pre[i]]);
ans += k * dis[t];
for(i = t ; i != s ; i = from[i]) val[pre[i]] -= k , val[pre[i] ^ 1] += k;
}
return ans;
}
int main()
{
int n , m , k , i , x;
scanf("%d%d%d" , &n , &m , &k) , s = 0 , t = n - m + 3;
add(s , 1 , k , 0) , add(n - m + 2 , t , k , 0);
for(i = 1 ; i <= n - m + 1 ; i ++ ) add(i , i + 1 , inf , 0);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%d" , &x);
if(i <= m) add(1 , i + 1 , 1 , -x);
else if(i > n - m) add(i - m + 1 , n - m + 2 , 1 , -x);
else add(i - m + 1 , i + 1 , 1 , -x);
}
printf("%d\n" , -mincost());
return 0;
}

【bzoj1283】序列 线性规划与费用流的更多相关文章

  1. 【bzoj1061】[NOI2008]志愿者招募 线性规划与费用流

    题目描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i ...

  2. [bzoj4842][bzoj1283][Neerc2016]Delight for a Cat/序列_线性规划_费用流

    4842: [Neerc2016]Delight for a Cat_1283: 序列 题目大意:ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜 ...

  3. [NOI2019]序列(模拟费用流)

    题意: 有两个长度为n的序列,要求从每个序列中选k个,并且满足至少有l个位置都被选,问总和最大是多少. \(1\leq l\leq k\leq n\leq 2*10^5\). 首先,记录当前考虑到的位 ...

  4. luogu P5470 [NOI2019]序列 dp 贪心 费用流 模拟费用流

    LINK:序列 考虑前20分 容易想到爆搜. 考虑dp 容易设\(f_{i,j,k,l}\)表示前i个位置 选了j对 且此时A选择了k个 B选择了l个的最大值.期望得分28. code //#incl ...

  5. P5470-[NOI2019]序列【模拟费用流】

    正题 题目链接:https://www.luogu.com.cn/problem/P5470 题目大意 两个长度为\(n\)的序列\(a,b\),求出它们两个长度为\(K\)的子序列,且这两个子序列至 ...

  6. 线性规划||网络流(费用流):COGS 288. [NOI2008] 志愿者招募

    [NOI2008] 志愿者招募 输入文件:employee.in   输出文件:employee.out   简单对比 时间限制:2 s   内存限制:512 MB [问题描述] 申奥成功后,布布经过 ...

  7. BZOJ1061 NOI2008 志愿者招募 线性规划、费用流

    传送门 一道思路很妙的线性规划网络流 设\(X_i\)表示第\(i\)天需要的人数,\(P_i\)表示第\(i\)种人雇佣的个数 那么我们可以列出一系列式子 比如说样例就可以列出三个式子: \(P_1 ...

  8. 【BZOJ1283/3550】序列/[ONTAK2010]Vacation 最大费用流

    [BZOJ1283]序列 Description 给出一个长度为 的正整数序列Ci,求一个子序列,使得原序列中任意长度为 的子串中被选出的元素不超过K(K,M<=100) 个,并且选出的元素之和 ...

  9. BZOJ1283 序列(费用流)

    不妨看做是先用k个指针指向被选择的前k个元素,然后每次将选中当前第一个元素的指针移到最后,并且需要满足位置变化量>=m.显然这样可以构造出所有的合法方案.那么可以以此建立费用流模型,以一条流量k ...

随机推荐

  1. 51nod 1101 换零钱

    基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 N元钱换为零钱,有多少不同的换法?币值包括1 2 5分,1 2 5角,1 2 5 10 20 50 100元.   ...

  2. JAVA多线程编程——JAVA内存模型

    一.何为“内存模型” 内存模型描述了程序中各个变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节,对象最终是存储在内存里面的,但是编译器 ...

  3. 并发教程--JAVA5中 计数信号量(Counting Semaphore)例子

    并发教程--JAVA5中 计数信号量(COUNTING SEMAPHORE)例子 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java中的计数信息量(C ...

  4. zend studio failed to create java virtual machine无法启动的解法

    zend studio failed to create java virtual machine 解决方案:在安装目录下修改ZendStudio.ini中第十四行处改成 -Xmx512M. -sta ...

  5. 解除phpMyAdmin导入大型MySQL数据库文件大小限制

    phpMyAdmin 导入大型数据库文件大小限制配置… 1. 修改 php.ini 文件中下列3项的值: upload_max_filesize, memory_limit 和 post_max_si ...

  6. java sql database相关收集

    1 java prepareStatement http://www.importnew.com/5006.html 2 java ENGINE=InnoDB的使用 http://www.cnblog ...

  7. WINDOWS-API:关于线程 GetCurrentThread、GetCurrentThreadId、GetCurrentProcess、GetCurrentProcessId

    {返回当前线程的虚拟句柄} GetCurrentThread: THandle; {返回当前线程 ID} GetCurrentThreadId: DWORD; {返回当前进程的虚拟句柄} GetCur ...

  8. Python基础篇 -- 集合

    set集合 set 中的元素是不重复的,无序的 里面的元素必须是可hash的,(int str tuple bool) set 就是dict 类型的数据,但是不保存value 只保存 key set集 ...

  9. Bootstrap历练实例:默认的面板(Panels)

    Bootstrap 面板(Panels) 本章将讲解 Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素 ...

  10. cocos2d-x之CCCardinalSplineBy

    CCCardinalSplineBy概念 这个类是样条曲线动作,其创建函数CCCardinalSplineBy::create(float duration, cocos2d::CCPointArra ...