「区间DP」「洛谷PP3146 」[USACO16OPEN]248 G
[USACO16OPEN]248 G
题目:
题目描述
Bessie likes downloading games to play on her cell phone, even though she doesfind the small touch screen rather cumbersome to use with her large hooves.
She is particularly intrigued by the current game she is playing.The game starts with a sequence of NNN positive integers (2≤N≤2482 \leq N\leq 2482≤N≤248), each in the range 1…401 \ldots 401…40. In one move, Bessie cantake two adjacent numbers with equal values and replace them a singlenumber of value one greater (e.g., she might replace two adjacent 7swith an 8). The goal is to maximize the value of the largest numberpresent in the sequence at the end of the game. Please help Bessiescore as highly as possible!
给定一个1*n的地图,在里面玩2048,每次可以合并相邻两个(数值范围1-40),问最大能合出多少。注意合并后的数值并非加倍而是+1,例如2与2合并后的数值为3。
输入格式
The first line of input contains NNN, and the next NNN lines give the sequence
of NNN numbers at the start of the game.
输出格式
Please output the largest integer Bessie can generate.
输入输出样例
输入 #1
4
1
1
1
2
输出 #1
3
说明/提示
In this example shown here, Bessie first merges the second and third 1s to
obtain the sequence 1 2 2, and then she merges the 2s into a 3. Note that it is
not optimal to join the first two 1s.
思路:
受区间DP题单的影响,上来想分成两种状态分别讨论,向左向右预处理合并,之后区间DP割点合并。
代码实现如下:
/*#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
name=$GEDIT_CURRENT_DOCUMENT_NAME
pre=${name%.*}
g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
if test $? -eq 0; then
gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
fi*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=505,INF=0x3f3f3f3f;
int n,f[2][maxn][maxn],a[maxn],m,ans;//1左0右
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}
int main(){
n=read();
for(int i=1;i<=n;i++){a[i]=read(),f[0][i][i]=f[1][i][i]=a[i],ans=max(ans,a[i]);}//预处理f[0][i][i]和f[1][i][i]
for(int i=1;i<n;i++){
if(a[i]==a[i+1])f[0][i][i+1]=f[1][i][i+1]=a[i]+1;//相等合并
else f[0][i][i+1]=a[i+1],f[1][i][i+1]=a[i];
ans=max(ans,max(f[0][i][i+1],f[1][i][i+1]));
//cout<<i<<" "<<i+1<<" "<<f[0][i][i+1]<<endl;
}//预处理f[0][i][i+1]和f[1][i][i+1]
for(int d=3;d<=n;d++){
for(int i=1,j;(j=i+d-1)<=n;i++){
if(f[0][i][j-1]==a[j])f[0][i][j]=a[j]+1;//能合并就合并
else f[0][i][j]=a[j];//不能合并要改为最右端的数否则无法继续向右合并
if(f[1][i+1][j]==a[i])f[1][i][j]=a[i]+1;//同理
else f[1][i][j]=a[i];
ans=max(ans,max(f[1][i][j],f[0][i][j]));
//cout<<i<<" "<<j<<" "<<f[0][i][j]<<endl;
}
}//向右向左合并预处理
for(int d=2;d<=n;d++){//左右合并
for(int i=1,j;(j=i+d-1)<=n;i++){
for(int k=i;k<j;k++){
if(f[0][i][k]==f[1][k+1][j])f[0][i][j]=f[1][i][j]=f[0][i][k]+1;//两个区间内的数值相等就可以合并,因为保证了断点左右数值一定代表左右区间的数值,这也是用两个状态的原因
// else f[0][i][j]=f[]
ans=max(ans,max(f[1][i][j],f[0][i][j]));
}
}
}
cout<<ans;
}
调了二十分钟扔了,望有缘人能调出来。
后来康了一眼题解发现想多了。其实不用两个状态,而且只用上面代码的最后一个合并就行
断点左右区间数值相等就合并,价值+1,否则就为0
代码:
/*#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
name=$GEDIT_CURRENT_DOCUMENT_NAME
pre=${name%.*}
g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
if test $? -eq 0; then
gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
fi*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=505,INF=0x3f3f3f3f;
int n,f[maxn][maxn],a[maxn],m,ans;//f[i][j]表示合并i-j的价值,当然如果i-j内不能合并,就为0,例如样例中f[3][4]=0
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}
int main(){
//freopen("a.in","r",stdin);
n=read();
for(int i=1;i<=n;i++){a[i]=read(),f[i][i]=a[i],ans=max(ans,a[i]);}
for(int i=1;i<n;i++){
if(a[i]==a[i+1])f[i][i+1]=a[i]+1;
// else f[i][i+1]=0;
ans=max(ans,f[i][i+1]);
//cout<<i<<" "<<i+1<<" "<<f[0][i][i+1]<<endl;
}//预处理一模一样
for(int d=2;d<=n;d++){
for(int i=1,j;(j=i+d-1)<=n;i++){
for(int k=i;k<j;k++){//有k+1右端点肯定不能超过j
if(f[i][k]==f[k+1][j]&&f[i][k]!=0)f[i][j]=f[i][k]+1;//如果两个区间i-k和k+1-j内的数值相同,那就合并。
//但是有一要求:两个区间内的数值不能为0,即两个区间必须本身能合并
ans=max(ans,f[i][j]);
}
//cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
}
}
cout<<ans;
}
over~
「区间DP」「洛谷PP3146 」[USACO16OPEN]248 G的更多相关文章
- 区间dp 能量项链 洛谷p1063
题目大意:如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为 (Mars单位),新产生的珠子的头标记为m,尾标记为n. 需要时,Mars人就用吸盘夹住 ...
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- 「区间DP」「洛谷P3205」「 [HNOI2010]」合唱队
洛谷P3205 [HNOI2010]合唱队 题目: 题目描述 为了在即将到来的晚会上有更好的演出效果,作为 A 合唱队负责人的小 A 需要将合唱队的人根据他们的身高排出一个队形.假定合唱队一共 n 个 ...
- 「洛谷5017」「NOIP2018」摆渡车【DP,经典好题】
前言 在考场被这个题搞自闭了,那个时候自己是真的太菜了.qwq 现在水平稍微高了一点,就过来切一下这一道\(DP\)经典好题. 附加一个题目链接:[洛谷] 正文 虽然题目非常的简短,但是解法有很多. ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- 「洛谷3870」「TJOI2009」开关【线段树】
题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...
- 「洛谷5283」「LOJ3048」「十二省联考2019」异或粽子【可持久化01trie+优先队列】
题目链接 [洛谷传送门] [LOJ传送门] 题目大意 让你求区间异或和前\(k\)大的异或和的和. 正解 这道题目是Blue sky大佬教我做的(祝贺bluesky大佬进HA省A队) 我们做过某一些题 ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- 「洛谷4197」「BZOJ3545」peak【线段树合并】
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...
随机推荐
- JNI_day02
二级指针 指向指针变量的指针,保存指针的地址 结构体 struct Student //struct Stdent 学生结构体类型 { int id;//成员 char name[20]; int a ...
- c#撸的控制台版2048小游戏
1.分析 最近心血来潮,突然想写一个2048小游戏.于是搜索了一个在线2048玩玩,熟悉熟悉规则. 只谈核心规则:(以左移为例) 1.1合并 以行为单位,忽略0位,每列依次向左进行合并,且每列只能合并 ...
- 前端JS的服务订阅&服务发布
var eventCenter = { sub:function(mesName, mesCallback){ this.argus=this.argus||{}; this.argus[mesNam ...
- redis的5种数据结构和基本操作
1.字符串(string) 1.1设置值 set key value [ex seconds] [px milliseconds] [nx|xx] 例如: 127.0.0.1:6379> set ...
- 怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏
这么说吧,在我眼里,Java 就是最流行的编程语言,没有之一(PHP 往一边站).不仅岗位多,容易找到工作,关键是薪资水平也到位,不学 Java 亏得慌,对吧? 那可能零基础学编程的小伙伴就会头疼了, ...
- Git中的core.autocrlf选项
项目的开发环境为Windows,在Linux环境下编译,使用Git进行版本控制. 在安装好Git和TortoiseGit后,从远端clone,遇到一个奇怪的问题,Shell脚本中的LF总是被替换成了C ...
- NASH:基于丰富网络态射和爬山算法的神经网络架构搜索 | ICLR 2018
论文提出NASH方法来进行神经网络结构搜索,核心思想与之前的EAS方法类似,使用网络态射来生成一系列效果一致且继承权重的复杂子网,本文的网络态射更丰富,而且仅需要简单的爬山算法辅助就可以完成搜索,耗时 ...
- 如何开发一个自己的npm包
目录 一.初始化npm包 二.新建自己的工具类 三.新建入口文件index.js 四.编写单元测试 五.登录仓库 六.发布包 七.安装使用 八.删除包 一.初始化npm包 npm init 运行输入包 ...
- 红米手机 android4.4.4 root之路
第一步: 进入360root官网下载apk安装包: http://root.360.cn/index.html 说明:不是所有的机型都能root, 一般android5.0 以下的系统root的成功 ...
- Redis系列(五):数据结构List双向链表中基本操作操作命令和源码解析
1.介绍 List是通过ListNode实现的双向链表. 1.双端:获取某个结点的前驱和后继结点都是O(1) 2.无环:表头的prev指针和表尾的next指针都指向NULL,对链表的访问都是以NULL ...