对于环形的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的更多相关文章

  1. Gym101889J. Jumping frog(合数分解+环形dp预处理)

    比赛链接:传送门 题目大意: 一只青蛙在长度为N的字符串上跳跃,“R”可以跳上去,“P”不可以跳上去. 字符串是环形的,N-1和0相连. 青蛙的跳跃距离K的取值范围是[1, N-1],选定K之后不可改 ...

  2. Luogu【P1880】石子合并(环形DP)

    先放上luogu的石子合并题目链接 这是一道环形DP题,思想和能量项链很像,在预处理过程中的手法跟乘积最大相像. 用一个m[][]数组来存储石子数量,m[i][j]表示从第 i 堆石子到第 j 堆石子 ...

  3. 区间DP中的环形DP

    vijos1312 链接:www.vijos.org/p/1312 题目分析:经典的环形DP(区间DP) 环形DP,首先解环过程,把数组复制一遍,n个数变成2n个数,从而实现解环 dp[i][j]表示 ...

  4. codevs1085数字游戏(环形DP+划分DP )

    1085 数字游戏  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单, ...

  5. P1880 [NOI1995]石子合并[环形DP]

    题目来源:洛谷 题目描述 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将 ...

  6. $Poj2228$/洛谷$SP283\ Naptime$ 环形$DP$

    Luogu 一定要记得初始化为-inf!!! Description 在某个星球上,一天由N小时构成.我们称0-1点为第一个小时,1-2点为第二个小时,以此类推.在第i个小时睡觉能恢复Ui点体力.在这 ...

  7. FZU - 2204 简单环形dp

    FZU - 2204 简单环形dp 题目链接 n个有标号的球围成一个圈.每个球有两种颜色可以选择黑或白染色.问有多少种方案使得没有出现连续白球7个或连续黑球7个. 输入 第一行有多组数据.第一行T表示 ...

  8. NOIP2009pj道路游戏[环形DP 转移优化 二维信息]

    题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将这 n 个机器人工厂编 ...

  9. 动态规划:区间DP与环形DP

    区间型动态规划的典型例题是石子归并,同时使用记忆化搜索实现区间动归是一种比较容易实现的方式,避免了循环数组实现的时候一些边界的判断 n堆石子排列成一条线,我们可以将相邻的两堆石子进行合并,合并之后需要 ...

随机推荐

  1. bootstrap table 的简单Demo

    暂时够用,不够用再补充 T_T script: <link rel="stylesheet" href="lib/bootstrap.min.css"&g ...

  2. Android App 安全的HTTPS 通信

    漏洞描述 对于数字证书相关概念.Android 里 https 通信代码就不再复述了,直接讲问题.缺少相应的安全校验很容易导致中间人攻击,而漏洞的形式主要有以下3种: 自定义X509TrustMana ...

  3. ASP.NET CORE下运行CMD命令

    ASP.NET CORE下运行CMD命令,用以前的ASP.NET 的命令System.Diagnostics.Process.Start("notepad");这样是可以运行出记事 ...

  4. Android recovery支持adb shell

    Android recovery支持adb shell 近期开发过程注意到recovery不支持adb shell.为了便于调试方便,决定添加此功能. 刚開始我们採用的是user版本号系统,进入rec ...

  5. 【Unity】微信支付SDK官方安卓Demo的使用问题

    Unity3d使用微信支付是属于APP内发起支付调用的情况,其本质上是在安卓项目上使用微信SDK,安卓项目开发完成后再导入到Unity中作为Unity插件使用,即Unity中C#调用安卓(Java)代 ...

  6. sping加载bean都发生了些什么

    问题描述:使用@Autowired注入的类,没有实例化 //Controller @RequestMapping(value="/deepblue") @Controller pu ...

  7. CAS单点登陆,URL多出个参数jsessionid导致登陆失败问题

    目录: 1.定位问题 2.问题产生的原因 3.解决问题 一 定位问题 首先,如下图所示:输入到地址栏的地址被302重定向到单点登录地址,地址由Response Headers中的参数Location所 ...

  8. 博客搬家了,新域名dinphy.wang

    博客搬家了,新域名      dinphy.wang 博客搬家了,新域名      www.dinphy.wang 博客搬家了,新域名      dinphy.wang 博客搬家了,新域名     w ...

  9. hdoj:2056

    #include <iostream> #include <iomanip> #include <cstdlib> using namespace std; str ...

  10. C# 正则表达式判断是否是数字、是否含有中文、是否是数字字母组合

    //判断输入是否包含中文 不管你有没有输入英文,只要包含中文,就返回 true public static bool HasChinese(string content) { //判断是不是中文 st ...