牛客寒假训练营1 K 冒险公社(线性dp)
先从样例模拟清楚题意:
...最后模拟可以得到答案4
题意:求前n个岛中最多的绿岛数,根据罗盘预测结果知道实际上绿岛数
dp做法
由于dp问题的使用条件是1.最优子结构 2.不具有后效性
本题是一个线性递推的过程,存在最优子结构
由于处于某一点时,当前的状态(什么颜色) 是会影响到后面两座岛屿的
所以我们可以多开几维,因为颜色就只有三种,可以枚举出来
最后的时间复杂度是O(n*3^4)
原问题:考虑前n个岛屿后,最多的绿岛数
子问题:考虑前i个岛屿,且i为a岛,i-1为b岛,i-2为c岛时的最多绿岛数
状态表示:dp[i][a1][a2][a3]
集合:所有考虑前i个岛屿,且i为a岛,i-1为b岛,i-2为c岛的所有集合
属性:max
可以发现
- 罗盘预测为green的所有集合都满足 g>r
- 罗盘预测为red的所有集合都满足g<r
- 罗盘预测为black的所有都满足g==r
根据划分依据:最后一个不同点,可以将集合划分为不重不漏的三个子集
- 当前罗盘为a 且 三个岛中g>r
- 当前罗盘为b 且 三个岛中g<r
- 当前罗盘为c 且 三个岛中g==r
边界:负无穷 (不满足预测的方案,他的值应该为负无穷或-1,表示不满足预测)
初始化:dp[3][..][..][..]=对应的绿岛数
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=1e5+10;
int dp[N][4][4][4];
int main()
{int n;cin>>n;string s;cin>>s;s=" "+s;memset(dp,-1,sizeof dp);//预处理前3个岛屿for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)for(int k=1;k<=3;k++){int g=0,r=0,b=0;if(i==1) g++;if(i==2) r++;if(i==3) b++;if(j==1) g++;if(j==2) r++;if(j==3) b++;if(k==1) g++;if(k==2) r++;if(k==3) b++;if(g<r&&s[3]=='R') dp[3][i][j][k]=g;if(g>r&&s[3]=='G') dp[3][i][j][k]=g;if(g==r&&s[3]=='B') dp[3][i][j][k]=g;}for(int i=4;i<=n;i++)for(int a=1;a<=3;a++)for(int b=1;b<=3;b++)for(int c=1;c<=3;c++){int g=0,r=0,bl=0;if(a==1) g++;if(a==2) r++;if(a==3) bl++;if(b==1) g++;if(b==2) r++;if(b==3) bl++;if(c==1) g++;if(c==2) r++;if(c==3) bl++;for(int l=1;l<=3;l++){if(dp[i-1][b][c][l]==-1) continue;//这句一定要加,如果这个方案下前面所有岛屿都不满足预测,即使当前岛屿满足预测,也是不符合条件的,所以应该让他直接跳过,不能用来更新
//也可以定义dp数组初值负无穷,res<0就代表无解if(g<r&&s[i]=='R')dp[i][a][b][c]=max(dp[i][a][b][c],dp[i-1][b][c][l]+(a==1));if(g>r&&s[i]=='G')dp[i][a][b][c]=max(dp[i][a][b][c],dp[i-1][b][c][l]+(a==1));if(g==r&&s[i]=='B')dp[i][a][b][c]=max(dp[i][a][b][c],dp[i-1][b][c][l]+(a==1));}}int res=-1;for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)for(int k=1;k<=3;k++)res=max(res,dp[n][i][j][k]);cout<<res;return 0;
}
优化
可以进一步对于状态进行优化
我们发现当前点会考虑前面两个点 i-1 i-2 而 i-1 会考虑前面两个点 i-2 i-3...
而其实i-3对于在第i点的状态转移是没有任何帮助的,根据上面的状态转移我们也发现了
所以其实可以把状态表示方程进一步的优化,优化成为三维的
原问题:考虑前n个岛屿,其中最多的绿岛数
子问题:考虑前i个岛屿,其中i为a岛,i-1为b岛的最大绿岛数
状态转移:根据定义,我们只需要记录两座岛的颜色,在状态转移的时候,确保前面两座岛的颜色都被考虑进入(i-1,i-2颜色都被枚举到),就可以达到不重不漏,而i-3是没有用的,所以可以舍弃
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=1e5+10;
int dp[N][4][4];
int main()
{int n;cin>>n;string s;cin>>s;s=" "+s;memset(dp,-0x3f,sizeof dp);for(int i=1;i<=3;i++)for(int j=1;j<=3;j++){int g=(i==1)+(j==1),r=(i==2)+(j==2);dp[2][i][j]=g;}for(int i=3;i<=n;i++)for(int a=1;a<=3;a++)for(int b=1;b<=3;b++)for(int c=1;c<=3;c++){int g=(a==1)+(b==1)+(c==1);int r=(a==2)+(b==2)+(c==2);if(g<r&&s[i]=='R')dp[i][a][b]=max(dp[i][a][b],dp[i-1][b][c]+(a==1));if(g>r&&s[i]=='G')dp[i][a][b]=max(dp[i][a][b],dp[i-1][b][c]+(a==1));if(g==r&&s[i]=='B')dp[i][a][b]=max(dp[i][a][b],dp[i-1][b][c]+(a==1));}int res=-0x3f3f3f3f;for(int i=1;i<=3;i++)for(int j=1;j<=3;j++)res=max(res,dp[n][i][j]);if(res<0)cout<<-1;elsecout<<res;return 0;
}
牛客寒假训练营1 K 冒险公社(线性dp)相关推荐
- 牛客寒假训练营4-爆炸的符卡洋洋洒洒 (dp变形)
题意: 链接:登录-专业IT笔试面试备考平台_牛客网 来源:牛客网 小红正在研究如何把符卡组合出尽可能大威力的组合魔法. 小红共有 n 种符卡可以选择,每种符卡最多只能选择一次,每个符卡的魔力消耗为 ...
- 【牛客 - 696D】小K的雕塑(dp,鸽巢原理,01背包类问题)
题干: 链接:https://ac.nowcoder.com/acm/contest/696/D 来源:牛客网 小K有n个雕塑,每个雕塑上有一个整数 若集合T中的每一个元素在n个雕塑上都能找得到,则称 ...
- 2021牛客寒假训练营5D石子游戏(差分)
这个题无解的情况后台数据高达80%,一开始过了10%以为写假了 光巨昨晚讲的太好了,今天上线写一下 题目大意: 给你n堆石子和一个区间k,每次对一个长度一定为k的区间里的所有数字加一,问最少操作次数使 ...
- 牛客寒假训练营6 阿宁睡不醒
题目: 题目链接:https://ac.nowcoder.com/acm/contest/46814/L 题意:输入n,m代表一个n*n的网格中有m个坏点,随后输入m行的x,y坐标,表示所有坏点的位置 ...
- 【牛客 - 315F】美丽的项链(线性dp,递推,我为人人)
题干: 妞妞参加了Nowcoder Girl女生编程挑战赛, 但是很遗憾, 她没能得到她最喜欢的黑天鹅水晶项链. 于是妞妞决定自己来制作一条美丽的项链.一条美丽的项链需要满足以下条件: 1.需要使用n ...
- 2022牛客寒假算法基础集训营3 签到题7题(附基础集训营1-3签到题总结)
1.A-智乃的Hello XXXX 签到 #include<bits/stdc++.h> using namespace std; int main(){cout<<" ...
- 2021牛客寒假算法基础集训营1 J 一群小青蛙呱蹦呱蹦呱
今天的比赛没打( 睡午觉去了,今天太累了 晚上来看看题 2021牛客寒假算法基础集训营1 J 一群小青蛙呱蹦呱蹦呱 题目传送门 板子题( 我们知道由唯一分解定理得,若 n=p1α1×p2α2×p3α3 ...
- 2022牛客寒假算法基础集训营6 签到题5题(附基础集训营4-6签到题总结)
1.I-A+B问题 模拟,类似于高精度,竖式运算 #include<bits/stdc++.h> using namespace std; typedef long long LL; in ...
- (构造+二进制)2020牛客寒假算法基础集训营3B.牛牛的DRB迷宫II
2020牛客寒假算法基础集训营3B.牛牛的DRB迷宫II 思路: 一开始我是考虑全部都是B会怎么样,然后删改,结果到后面发现很难推到普遍规律(可能是因为我没看出来). 看了题解之后,觉得这题出的挺有意 ...
- 构造-牛客寒假集训营3-牛牛的DRB迷宫II
构造-牛客寒假集训营3-牛牛的DRB迷宫II 题目: 题意: 输入一个数字,表示从起点(1,1)到终点(n,m)的方案数量,输出满足条件的迷宫.输入一个数字,表示从起点(1,1)到终点(n,m)的方案 ...
最新文章
- from __future__ import absolute_import, division, print_function
- pelco协议及其实现的简单认识
- hadoop交流群261039241
- 008/160 CrackMe Andrénalin #1
- Grand Canyon
- zookeeeper 启动失败 Unexpected exception, exiting abnormally java.io.eofexception
- git fsck --lost-found
- MacOS安装brew
- 游戏辅助制作核心----植物大战僵尸逆向之加速出僵尸(十)
- 看懂DNS到HttpDNS
- 计算机领域经典故事,[转载]计算机的工作原理(1):一个经典的故事
- 咦,为什么我的事务回滚不了?
- Elasticsearch+X-pack和Java Transport方式连接
- NSSCTF刷题wp——常用编码
- android开发和手游开发工具,developer盘点Android开发者必备十大开发工具
- 3d建模沟通能力,技术能力,更容易往主管,经理等管理方向发展
- 开发者模式的微信公众号菜单链接其他开发者的小程序
- 消除“你可能是盗版软件受害者”的提示(XP蓝星)
- 对于reflect: Elem of invalid type main.User类型的错误解释
- Mstar Amlogic智能电视芯片
热门文章
- ucml 连接虚字段
- 数字转成人民币汉字大写(李刚著《疯狂Python讲义》P87,解决小数部分及多个零的问题。学习笔记)
- python自动注册邮箱_Python自动登录126邮箱的方法
- 未来的计算机范文,未来的电脑作文(通用3篇)
- 分治策略-股票获取最大收益-最大子数组问题
- 准考证丢失后如何查询四六级成绩
- 龟兔赛跑Description乌龟与兔子在马路上赛跑,马路边可以随地进行休息。
- 2021最全HW蓝队指导手册
- 《数据库原理与应用》学习笔记(一):概论
- Drillbeach---第二章 Drillbench 5.1 Dynaflodrill 用户指南