【bzoj4580】[Usaco2016 Open]248 区间dp

本文介绍了一个基于区间动态规划的游戏策略问题。目标是在一系列正整数中通过合并相邻且相等的数来形成尽可能大的数值。文章详细解释了如何定义状态f[i][j]并给出了完整的C++代码实现。

题目描述

Bessie likes downloading games to play on her cell phone, even though she does find the small touch 
screen rather cumbersome to use with her large hooves.She is particularly intrigued by the current g
ame she is playing. The game starts with a sequence of NN positive integers (2≤N≤248), each in the
 range 1…40. In one move, Bessie can take two adjacent numbers with equal values and replace them a
 single number of value one greater (e.g., she might replace two adjacent 7s with an 8). The goal is
 to maximize the value of the largest number present in the sequence at the end of the game. Please 
help Bessie score as highly as possible!

输入

The first line of input contains N, and the next N lines give the sequence of N numbers at the start
 of the game.

输出

Please output the largest integer Bessie can generate.

样例输入

4
1
1
1
2

样例输出

3


题目大意

给你n个数的数列,每次可以合并两个相邻且相等的数,变成大小比原数大1的新数。问可能出现的最大的数是多少。

题解

区间dp

首先必须明确一点,如果一段区间能够按照题目要求合并成一个数,那么这个数一定是确定的。

那么可以设f[i][j]为i到j这段区间合并成的数,如果无法合并则为0。

那么就有f[i][j]=f[i][k]+1(f[i][k]==f[k+1][j]&&f[i][k]!=0)。

答案就是max{f[i][j]}。

注意需要先枚举长度再枚举起始点。

#include <cstdio>
#include <algorithm>
using namespace std;
int f[250][250];
int main()
{
	int n , i , j , k , ans = 0;
	scanf("%d" , &n);
	for(i = 1 ; i <= n ; i ++ )
		scanf("%d" , &f[i][i]);
	for(i = 2 ; i <= n ; i ++ )
		for(j = 1 ; j <= n - i + 1 ; j ++ )
			for(k = j ; k <= i + j - 2 ; k ++ )
				if(f[j][k] && f[k + 1][i + j - 1] && f[j][k] == f[k + 1][i + j - 1])
					f[j][i + j - 1] = f[j][k] + 1;
	for(i = 1 ; i <= n ; i ++ )
		for(j = i ; j <= n ; j ++ )
			ans = max(ans , f[i][j]);
	printf("%d\n" , ans);
	return 0;
}

 

转载于:https://www.cnblogs.com/GXZlegend/p/6434903.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值