蓝桥杯训练题1255: [蓝桥杯][算法提高]能量项链【找规律,寻找最优情况,然后利用一维数组和二维数组进行相应乘和加操作算出答案】

题目链接:

https://www.dotcpp.com/oj/problem1255.html

题目大意:

先是给你一个数字N,代表后面有几个数字,然后每个数字和这个数字后面一位,两个整体看做成一个能量珠,其实就是一个二维数组啦。然后如果这个数字是最后面一位的话,那么这位数字的后面一位就认为是第1位,就相当于是把这个数字看成两个数字地圈。然后圈号的数字按照下面的规则去依次乘积,算出所有乘积最大的和。
比如:题目给的:N=4,
然后后面四个数字分别是:2,3,5,10
那么我们就可以得到相对应的四个珠:{2,3},{3,5},{5,10},{10,2}
*************************************珠: ①、 ②、、③、、④
然后需要我们这样乘:比如:我们让①和②合并,那么就是得到:这个值为:2×3×5,然后得到一个新的珠,为{2,5},我们称为⑤号珠。就是按照这种方式一直找下去,一直合并到一个珠为止,当然其中的值是需要记录的。

然后嘞,就是让我们找到一种最佳的合并方式使得珠合并产生的总值最大化,并且让我们输出这个值。

那么这个{2,3},{3,5},{5,10},{10,2}的最大化合并方式就是:
((④×①)×②)×③ = 10×2×3 + 10×3×5+10×5×10=60+150+500=710

思路:

首先就是先将这些数字用个一维数组val[105]给存起来也就是上面说到的这个“2,3,5,10”
然后通过val数组来构造出相对应的能量珠,而其中的值就用二维数组num[105][2]来存储也就是这个“{2,3},{3,5},{5,10},{10,2}”。
然后我们会发现,一维数组里的值在二维数组里面都会出现两次。然后,我们可以看到,只要我们将二维数组里的数按照一维数组里最小的值给消掉,那么剩下的数再去乘,这样可定时最优的。
那么也就是说我们消得顺序只要按照一维数组从小到大地顺序来就可以了。
比如:
N = 4,
5 6 3 4.
这个构造出来的一维数组为{5,6,3,4},
二维数组为{{5,6},{6,3},{3,4},{4,5}},
然后需要将一维数组排下序变为:{3,4,5,6}
①那么就先消3咯,找到二维数组中含有3的,即{6,3},{3,4},算出值:6×3×4=72,二维数组也随之变为{{5,6},{6,4},{0,0},{4,5}},
②再消4:找到二维数组有4的,即{6,4},{4,5}算出值为:6×4×5=120,二维数组也随之变为{{5,6},{6,5},{0,0},{0,0}},
③再消5:找到5的即:{6,5},{5,6}值变为:6×5×6=180
输出最终值ans=①+②+③=72+120+180=372
在这里插入图片描述

ac代码:

#include <stdio.h>
 

typedef long long ll;

int n;
int val[105];
int num[105][2];//用来存储对应能量珠的前后值 
ll ans;//记录最后的答案 
void init(){//初始化二维数组即:初始化能量珠的值 
	int next;
	for(int j = 1;j <= n;j++){
		next = j+1;
		if(next > n){
			next = 1;
		}
		num[j][0] = val[j];
		num[j][1] = val[next];
	}
}


void sort(){//给一维数组排序 
	int temp;
	for(int h = 1;h <= n-1;h++){
		for(int k = h+1;k <= n;k++){
			if(val[k] < val[h]){
				temp = val[k];
				val[k] = val[h];
				val[h] = temp;
			}
		}
	}
}

void solve(){//用来处理二维数组的合并,并且记录合并产生的值 
	int temp;
	int index;
	int temp2;
	for(int i = 1;i < n;i++){
		temp = -1;
		index = -1;
		temp2 = -1;
		for(int j = 1;j <= n;j++){
			if(num[j][0]==0){
				continue;
			}
			if(num[j][0] == val[i]){//二维数组中第一位与一维数组值相等 
				temp = num[j][1];
				if(index != -1){
					num[index][1] = num[j][1];
				}
				
				num[j][0] = 0;
				num[j][1] = 0;
			}
			if(num[j][1] == val[i]){//第二位与一维数组中的值相等 
				temp2 = num[j][0];
				index = j;
				if(temp != -1){
					num[j][1] = temp;
				}
			}
		}
		ans += temp*temp2*val[i];

	} 
	
}


int main(){
	scanf("%d",&n);
	for(int i = 1;i <= n;i++){
		scanf("%d",&val[i]);
	}
	init(); 
	sort();
	ans = 0; 
	solve();
	printf("%lld\n",ans);
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值