USACO 2016 US Open【262144游戏】

本文介绍了一款数字合并游戏的算法解决方案,玩家需要通过合并相同数值的相邻数字来获得尽可能大的数值。文章详细阐述了如何利用动态规划的方法来解决这个问题,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Bessie喜欢在手机上下载游戏玩(……),然而她蹄子太大,很难在小小的手机屏幕上面操作。

她被她最近玩的一款游戏迷住了,游戏一开始有n个正整数,(2<=n<=262144),范围在1-40。每一步中,贝西可以选相邻的两个相同的数,然后合并成一个比原来的大一的数(例如两个7合并成一个8),直到不能合并,游戏结束,目标是使得最后最大的数最大,请帮助Bessie来求最大值。

Input Format

输入格式:(262144.in)

第一行n,然后n行分别是开始游戏时每一个数。

Output Format

输出格式:(262144.out)

Bessie能生成的最大的数。

Sample Input

4
1
1
1
2

Sample Output

3

Hint

样例解释

将第二个和第三个1合并成2,然后两个2合并成3。

过程:

1 1 1 2

1 2 2

1 3

【题解】

一题 题目不水,数据很水的动归题(说数据水是因为,随便搞搞都能过,貌似各种不正确贪心,甚至是正反两遍for能和则和,也能过 )

个人觉得这题很类似于倍增的前期预处理(f[i][j]=f[f[i][j-1]][j-1])(不知道为啥很多人觉得像合并类动归)

仔细思考不难发现,本题一个区间内的数不一定可以完全合并,因此,状态单记录合成数值,或者区间范围是不可取的

因此状态设计时必须强制使得一段区间内的所有数都被合并,看一下数据范围如果把区间的两个端点都表示在状态里面也是不可取的(爆内存啊)

后来发现其实一段区间完全合并数字是确定的,所以知道了一个端点知道合并出来的值另一个端点也就确定了,刚好数字又特别小(最多就58)所以就在状态里面表示一个端点和所合成的数值,那状态就设计出来了233(f[j][i])表示以第j个数为左端点数值为i时右端点的位置

所以就出现了一个与倍增特别相似的转移方程f[j][i]=f[f[j][i-1]+1][i-1] 然后程序就特别好写了初始值就是f[i][a[i]]=i;

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
#include <map>
using namespace std;
int i,j,k,l,m,n;
int f[262200][65],a[262200];
int main()
  {
  	scanf("%d",&n);
  	for (i=1;i<=n;i++) scanf("%d",&a[i]),f[i][a[i]]=i,m=max(m,a[i]);
  	for (i=1;i<=m;i++)
  	  {
  	  	for (j=1;j<=n;j++)
  	  	  if (f[j][i]!=0&&f[f[j][i]+1][i]!=0) 
  	  	    {
				f[j][i+1]=f[f[j][i]+1][i];
				if (i+1>m) m=i+1;
		    }
	  }
	printf("%d",m);
  }


### USACO 2016 Copper Problems and Information USACO(United States of America Computing Olympiad)是一个面向全球编程爱好者的竞赛平台,尤其受到高中生欢迎。对于2016年的铜级别比赛,以下是几个具有代表性的题目及其描述: #### Promotion Counting 【USACO 2016 January Contest, Bronze】 在这个问题中,给定一组奶牛的位置以及它们晋升的情况,需要统计特定条件下能够被提升的奶牛数量[^1]。 ```cpp // 这里提供的是一个简化版的例子用于说明逻辑结构而非具体实现细节 #include <iostream> using namespace std; int main(){ int n; cin >> n; // 处理输入并计算结果... } ``` #### Cities and States 【USACO 2016 December Contest, Silver but mentioned in bronze context】 此题涉及城市名称和州名之间的匹配关系。给出多个城市的名称其所在的州缩写,要求找出满足一定条件的城市对的数量[^2]。 ```cpp // 同样仅展示框架性代码片段 string city_names[], state_codes[]; for (each pair){ check_condition_and_count(); } cout << count_result; ``` #### Angry Cows 【USACO 2016 January Contest, Bronze】 这是一个关于覆盖区间的问题。假设有一系列位于直线上的目标点(草堆),通过调整发射物(奶牛)的影响范围来尽可能高效地摧毁所有目标。任务是要找到最小的有效影响半径使得全部目标都能受到影响[^3]。 ```cpp vector<int> positions; // 存储各个草堆的位置 double findMinRadius(int k){ /* ... */ } ``` #### Circular Barn 【USACO 2016 February Contest, Bronze】 该问题是围绕着优化路径展开的。在一个环形布局下安排访问顺序,目的是使总的行走距离最短。解决方案涉及到遍历不同的起始位置,并评估由此产生的总成本,最终选取最优解[^4]。 ```cpp LL solveOptimalPath(vector<int>& distances){ LL bestCost = numeric_limits<LL>::max(); for(size_t start=0 ;start<distances.size();++start){ calculate_cost_from_start(start); update_best_if_better(bestCost,currentCost); } return bestCost; } ``` 这些例子展示了不同类型的算法挑战,从简单的计数到更复杂的贪心策略或是动态规划方法的应用。每个问题都旨在测试参赛者的基础编程技能以及解决问题的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值