环形dp
对于环形的dp 大多情况都是破环成链 例如 那道宝石手镯的环形 一般来说都是要破环成链的。
或者说 是 两次dp 一次断开 一次强制连接即可。
我想 我应该沉淀下来了这些天写的题都有点虚 要不就是看了书 要不就是点开了题解总是在自己未想出的时候 外物影响到我让我感觉特别没有成就感呢。
这就很不爽了 我觉得是真的不爽 ,算了按照原计划行事(oj刷上520)

这道题目 看起来很简单 我的意思是指 很轻而易举的列出来状态和 状态转移方程 事实上也是如此 。
但是唯一难以处理的是 环形的结构 。。我设状态 因为要知道前面那个到底选了没有所以必须要写两个选或不选的状态。
设 f[i][j][0/1] 表到了第i个小时已经形成j段且第i个小时选 0 不选 1。
f[1][1][0]=0; f[1][0][1]=0;
显然 f[i][j][0]=max(f[i-1][j-1][1],f[i-1][j-1][0]+v[j]); f[i][j][1]=max(f[i][j][0],f[i][j][1]);
对于环形的 上述我们断开dp一次了 此时为了弥补刚才断开的后果我们必须要连接上去。
此时状态必然是 f[1][1][0]=v[1]; 此时我们再进行上述dp 然后强制取答案 f[n][k][0]即可。
此时 B<n因为这道题保证了 那么在从一段数到最后的n一定有一个点会做铺垫。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
#define ll long long
#define R register
#define mod 45989
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline ll read()
{
ll x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(ll x)
{
x<?putchar('-'),x=-x:;
ll num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const ll MAXN=;
ll n,k,ans,u,cnt,minn=INF;
ll v[MAXN];
ll f[][MAXN][];
inline ll min(ll x,ll y){return x>y?y:x;}
inline ll max(ll x,ll y){return x>y?x:y;}
//f[i][j][k] 表 前i个小时 分成了j段 且在第 i的小时休息 0 还是不休息 1
int main()
{
//freopen("1.in","r",stdin);
n=read();k=read();
for(ll i=;i<=n;++i)v[i]=read();
if(n==k){for(ll i=;i<=n;++i)cnt+=v[i],minn=min(minn,v[i]);put(cnt-minn);}
memset(f,0xcf,sizeof(f));
f[u][][]=;f[u][][]=;
for(ll i=;i<=n;++i)
{
u=u^;
for(ll j=;j<=min(i,k);++j)
{
f[u][j][]=-INF;f[u][j][]=-INF;
f[u][j][]=max(f[u^][j][],f[u^][j][]);
if(j->=)f[u][j][]=max(f[u^][j-][],f[u^][j-][]+v[i]);
}
}
ans=max(ans,max(f[u][k][],f[u][k][]));
u=;
memset(f,0xcf,sizeof(f));
f[u][][]=v[];
for(ll i=;i<=n;++i)
{
u=u^;
for(ll j=;j<=min(i,k);++j)
{
f[u][j][]=-INF;f[u][j][]=-INF;
f[u][j][]=max(f[u^][j][],f[u^][j][]);
if(j->=)f[u][j][]=max(f[u^][j-][],f[u^][j-][]+v[i]);
}
}
ans=max(ans,f[u][k][]);
put(ans);
return ;
}
一次断开 一次联合 强制联合 。这样即可消除环形带来的影响。
这样的做法当然还可以 用在创世纪上,当然我是不会的。

这道题的思路就比较简单了 n为le6 显然 也是一个dp类型的题目 瞬间单调队列O(1)寻找决策即可。
至于环形 考虑再续上一段 因为在这一段上两点之间的距离如果大于n/2的话那么此时再续上的一段两点之间的距离就小于了 这样我们就可以直接在这一条链上做了。
然后进行决策转移和决策单调性维护即可。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
#define ll long long
#define R register
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline ll read()
{
ll x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(ll x)
{
x<?putchar('-'),x=-x:;
ll num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const ll MAXN=;
ll maxx,n;
ll a[MAXN],q[MAXN],l,r;
int main()
{
//freopen("1.in","r",stdin);
n=read();l=;r=;
for(ll i=;i<=n;++i)a[i]=read(),a[i+n]=a[i];
for(ll i=;i<=n+n/;++i)
{
while(l<=r&&i-q[l]>n/)++l;
if(l<=r)maxx=max(maxx,a[i]+a[q[l]]+i-q[l]);
while(l<=r&&a[q[r]]-q[r]<a[i]-i)--r;
q[++r]=i;
}
put(maxx);
return ;
}
环形dp的更多相关文章
- Gym101889J. Jumping frog(合数分解+环形dp预处理)
比赛链接:传送门 题目大意: 一只青蛙在长度为N的字符串上跳跃,“R”可以跳上去,“P”不可以跳上去. 字符串是环形的,N-1和0相连. 青蛙的跳跃距离K的取值范围是[1, N-1],选定K之后不可改 ...
- Luogu【P1880】石子合并(环形DP)
先放上luogu的石子合并题目链接 这是一道环形DP题,思想和能量项链很像,在预处理过程中的手法跟乘积最大相像. 用一个m[][]数组来存储石子数量,m[i][j]表示从第 i 堆石子到第 j 堆石子 ...
- 区间DP中的环形DP
vijos1312 链接:www.vijos.org/p/1312 题目分析:经典的环形DP(区间DP) 环形DP,首先解环过程,把数组复制一遍,n个数变成2n个数,从而实现解环 dp[i][j]表示 ...
- codevs1085数字游戏(环形DP+划分DP )
1085 数字游戏 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单, ...
- P1880 [NOI1995]石子合并[环形DP]
题目来源:洛谷 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将 ...
- $Poj2228$/洛谷$SP283\ Naptime$ 环形$DP$
Luogu 一定要记得初始化为-inf!!! Description 在某个星球上,一天由N小时构成.我们称0-1点为第一个小时,1-2点为第二个小时,以此类推.在第i个小时睡觉能恢复Ui点体力.在这 ...
- FZU - 2204 简单环形dp
FZU - 2204 简单环形dp 题目链接 n个有标号的球围成一个圈.每个球有两种颜色可以选择黑或白染色.问有多少种方案使得没有出现连续白球7个或连续黑球7个. 输入 第一行有多组数据.第一行T表示 ...
- NOIP2009pj道路游戏[环形DP 转移优化 二维信息]
题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将这 n 个机器人工厂编 ...
- 动态规划:区间DP与环形DP
区间型动态规划的典型例题是石子归并,同时使用记忆化搜索实现区间动归是一种比较容易实现的方式,避免了循环数组实现的时候一些边界的判断 n堆石子排列成一条线,我们可以将相邻的两堆石子进行合并,合并之后需要 ...
随机推荐
- iOS Xcode 10: Multiple commands produce
Xcode自动升级到10.0 1.编译的时候报错:Multiple commands produce 解决办法:File -> Workspace Setting -> build sys ...
- Mac NPM 配置
1.NPM 简介 NPM(node package manager),通常称为 node 包管理器,是目前世界上最大的开源库生态系统.使用 NPM 可以对 node 包进行安装.卸载.更新.查看.搜索 ...
- linux内存管理之malloc、vmalloc、kmalloc的区别
kmalloc kzalloc vmalloc malloc 和get_free_page()的区别 一.简述 1. kmalloc申请的是较小的连续的物理内存,虚拟地址上也是连续的.kmalloc和 ...
- CSS-2
day 39 学习链接:https://www.cnblogs.com/yuanchenqi/articles/5977825.html 4 文本属性 font-size: 10px; text-a ...
- Tomcat线程数与处理速度的关系
问题:Tomcat线程数是不是越大越好呢? 答案肯定是否定的. Tomcat的处理速度跟线程数不是完全成正比的,设置不恰当会出现相反的效果.服务的负载计算包括了CPU的使用率和资源等待. 第一种情况, ...
- vue 实站技巧总结
多个页面都使用的到方法,放在 vue.prototype上会很方便 刚接触 vue的时候做过一件傻事,因为封装了一个异步请求接口post,放在 post.js文件里面,然后在每个需要使用异步请求的页面 ...
- SQL Server 2016新特性:Live Query Statistics
SSMS可以提供可以查看正在执行的计划.live query plan可以查看一个查询的执行过程,从一个查询计划操作到另外一个查询计划操作.live query plan提供了整体的查询运行进度和操作 ...
- Centos7 Mysql5.7主从服务器配置
在两台Linux机器上安装MySQL 一.Master主服务器配置1.编辑my.cnf(命令查找文件位置:find / -name my.cnf)vi /etc/mysql/my.cnf 在[mysq ...
- mybatis 映射器(mappers) 配置说明 加载映射文件方式
映射器(mappers) 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了.但是首先我们需要告诉 MyBatis 到哪里去找到这些语句. Java 在自动查找这 ...
- 同样:Hashtable较HashMap也是如此。
练习: ① 存车位的停开车的次序输出问题: ② 写两个线程,一个线程打印1-52,另一个线程答应字母A-Z.打印顺序为12A34B56C……5152Z.通过使用线程之间的通信协调关系. 注:分 ...