你是一只小跳蛙,你特别擅长在各种地方跳来跳去。
为了给小 F 展现你超级跳的本领,你决定跳到每个石头上各一次,并最终停在任意一块石头上,并且小跳蛙想耗费尽可能多的体力值。
当然,你只是一只小跳蛙,你只会跳,不知道怎么跳才能让本领更充分地展现。
不过你有救啦!小 F 给你递来了一个写着 AK 的电脑,你可以使用计算机程序帮你解决这个问题,万能的计算机会告诉你怎么跳。
那就请你——会写代码的小跳蛙——写下这个程序,为你 NOIp AK 踏出坚实的一步吧!
输入格式
输入一行一个正整数 nn,表示石头个数。
输入第二行 nn 个正整数,表示第 ii 块石头的高度 h_ih
i
。
输出格式
输出一行一个正整数,表示你可以耗费的体力值的最大值。
输入 #1复制
2
2 1
输出 #1复制
5
输入 #2复制
3
6 3 5
输出 #2复制
49
说明/提示
样例解释
两个样例按照输入给定的顺序依次跳上去就可以得到最优方案之一。
巩固下贪心算法,这个题当时第一次做的时候有五个测试点没过,原因后来找到了算体力要用long long型数据储存,因为平方太大,只能用这个了。。。
看到比较大的数据还是果断用long吧
其实贪心的本质就是部分最优解,从而达到整体的最优解。
–这一题要消耗体力最多,那么我只要跳的每一步都要尽可能的消耗体力,这就是局部的最优解。试想,每一步消耗的体力都是最多的,那么最后消耗体力的总和就是最多的。
1.但要注意第一步和后面的步数是不一样的(类似分段函数),所以我们先输入完所有石头的高度之后,先按照从大到小对高度排序,这个时候排在数组第一位的就是高度最大的,这个时候先算第一个,后面的步数再分来来算。
2.后面要尽可能多的消耗体力,不难理解只需要每一次跳石头消耗体力相差最大就好了,但是如何实现呢?
这里我采用了类似二分的思想,一前一后,计算距离,每次计算都让相应下标增加/减少,当前面的下标大于后面的下标的时候,循环结束
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
long long h[301];
long long sum = 0;//切记用longlong
int start, end;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> h[i];
}
sort(h, h + n,greater<int>());
start = 0;
end = n-1;
sum = sum + h[0] * h[0];//先算第一步消耗的体力
while (start<end)//类似二分思想,求消耗体力最多最大
{
sum = sum + (h[start] - h[end]) * (h[start] - h[end]);
start++;
sum = sum + (h[start] - h[end]) * (h[start] - h[end]);
end--;
}
cout << sum;
return 0;
}