环形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堆石子排列成一条线,我们可以将相邻的两堆石子进行合并,合并之后需要 ...
随机推荐
- __NSArrayI __NSArray0 __NSSingleObjectArrayI __NSPlaceholderArray __NSArrayM
如果你的 全局 可变数组 前面 用了 copy修饰,那么 调用 arr addObjectsFromArray: 的时候 就 会崩溃,而且提示你 是 [__NSArray0 addObje ...
- Future、FutureTask实现原理浅析(源码解读)
前言 最近一直在看JUC下面的一些东西,发现很多东西都是以前用过,但是真是到原理层面自己还是很欠缺. 刚好趁这段时间不太忙,回来了便一点点学习总结. 前言 最近一直在看JUC下面的一些东西,发现很多东 ...
- php生成毫秒时间戳的例子
php时间函数time()生成当前时间的秒数,但是在一些情况下我们需要获取当前服务器时间和GMT(格林威治时间)1970年1月0时0分0秒的毫秒数,与Java中的currentTimeMilis()函 ...
- 各种容器与服务器的区别与联系:Servlet容器、WEB容器、Java EE容器、应用服务器、WEB服务器、Java EE服务器
1.容器与服务器的联系 如上图,我们先来看下容器与服务器的联系:容器是位于应用程序/组件和服务器平台之间的接口集合,使得应用程序/组件可以方便部署到服务器上运行. 2.各种容器的区别/联系 2-1.容 ...
- 【GMT43智能液晶模块】例程十三:FATFS实验——文件操作
实验原理: STM32F429上带有SDIO控制器,GMT43液晶模块上将SDIO连接到TF卡座.本实验 将Micro SD卡插入TF卡座上即可.通过FATFS创建test.txt文件,并且写入数据0 ...
- 【iCore4 双核心板_uC/OS-II】例程二:任务的建立与删除
一.实验说明: 本例程建立三个任务,通过任务寄存器来实现任务的建立与删除功能.红灯和绿灯同时以固定 频率闪烁,当任务寄存器为5时,删除绿灯闪烁的任务LED1,此时只有红灯闪烁,当任务寄存器的 值为10 ...
- 【转】Eclipse 乱码 解决方案总结(UTF8 -- GBK)
转载自: http://www.cnblogs.com/bluestorm/archive/2012/09/20/2695567.html UTF8 --> GBK; GBK --> ...
- go语言fallthrough的用法心得
fallthrough:Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch, 但是可以使用fallthrough强制执行后面 ...
- 危险代码:如何使用Unsafe操作内存中的Java类和对象
危险代码:如何使用Unsafe操作内存中的Java类和对象—Part1 危险代码:如何使用Unsafe操作内存中的Java类和对象—Part2 危险代码:如何使用Unsafe操作内存中的Java类和对 ...
- [转]谈NAND Flash的底层结构和解析
这里我想以一个纯玩家的角度来谈谈关于NAND Flash的底层结构和解析,可能会有错误的地方,如果有这方面专家强烈欢迎指正. NAND Flash作为一种比较实用的固态硬盘存储介质,有自己的一些物理特 ...