小Q和牛博士在玩一个石子合并的游戏,初始一共有n堆石子,每堆石子有w[i]个石子。小Q和牛博士他们需要对石子堆进行合并,每次他们可以任意选择两堆石子进行合并。一堆有x个石子的石子堆和一堆有y个石子的石子堆合并将得到一堆x+y个石子的石子堆,这次合并得分为x*y,当只剩下一堆石子的时候游戏结束。
、小Q和牛博士希望采取优秀的策略获得最大得分,希望你能来帮他们算算最大得分多少。
小Q和牛博士在玩一个石子合并的游戏,初始一共有n堆石子,每堆石子有w[i]个石子。小Q和牛博士他们需要对石子堆进行合并,每次他们可以任意选择两堆石子进行合并。一堆有x个石子的石子堆和一堆有y个石子的石子堆合并将得到一堆x+y个石子的石子堆,这次合并得分为x*y,当只剩下一堆石子的时候游戏结束。
、小Q和牛博士希望采取优秀的策略获得最大得分,希望你能来帮他们算算最大得分多少。
输入包括两行,第一行一个正整数n(2≤n≤100)。
第二行包括n个正整数w[i](1≤w[i]≤100),即每堆石子的个数。
输出一个正整数,即小Q和牛博士最大得分是多少。
3 1 2 3
11
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.Stack; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine().trim()); String[] strStone = br.readLine().trim().split(" "); int score = 0; Stack<Integer> stack = new Stack<>(); for(int i = 0; i < n; i++) stack.push(Integer.parseInt(strStone[i])); // 直接对栈顶的两堆石子弹出进行合并,合并结果再压入站中,重复这一过程直至栈中只有一堆石子 while(stack.size() > 1){ int num1 = stack.pop(); int num2 = stack.pop(); score += num1*num2; stack.push(num1 + num2); } System.out.println(score); } }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n =sc.nextInt(); int[] arr = new int[n]; for(int i=0;i<n;i++){ arr[i] = sc.nextInt(); } Arrays.sort(arr); int sum = 0; int num = arr[0]; for(int i=1;i<n;i++){ sum = sum+arr[i]*num; num = num + arr[i]; } System.out.println(sum); } }
#include <bits/stdc++.h> using namespace std; int main(){ int n,x,y; while(cin>>n) { priority_queue<int, vector<int>, greater<int>> q; for(int i=0;i<n;i++) { cin>>x; q.push(x); } int s = 0; while(q.size()>1) { x = q.top(); q.pop(); y = q.top(); q.pop(); s += x*y; q.push(x+y); } cout<<s<<endl; } return 0; }
#include <iostream> using namespace std; int main() { int n; cin >> n; int stock = 0, score = 0; for(int curr; cin >> curr; ) { score += stock * curr; stock += curr; } cout << score; }
其实顺序完全不影响的。无论什么顺序都是一样的结果。
设w1,w2,...,wn是一个任意的合并顺序(即先取w1,之后w1和w2合并,再之后w1 + w2,w3合并……)
在该合并顺序下的得分为:
将上面的式子乘以二,再将含有w1,w2,...wn的项提出来(把下面的和上面的对比你会发现每一个都多用了一遍),得到:
记,那么其实总得分就是
,与具体序列的顺序无关,只与序列元素的值有关。
import java.util.*; public class Main { private static final int MAX = 105; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] arr = new int[MAX]; for (int i=1; i<=n; i++) { arr[i] = sc.nextInt(); } int ans = 0, cur = arr[1]; for (int i=2; i<=n; i++) { ans += cur * arr[i]; cur += arr[i]; } System.out.println(ans); return; } }
package main import ( "fmt" "sort" ) func main() { var n int fmt.Scan(&n) arr:=make([]int,n) for i:=0;i<n;i++{ fmt.Scan(&arr[i]) } sort.Ints(arr) ans:=0 for len(arr)>1{ x,y:=arr[len(arr)-2],arr[len(arr)-1] ans+=x*y arr=append(arr[:len(arr)-2],x+y) } fmt.Print(ans) }
两两乘积求和就完事了,为毛要排序? n=int(input()) w=[int(i) for i in raw_input().split(' ')] s=0 for i in range(n-1): for j in range(i+1,n): s+=w[i]*w[j] print s
#include <stdio.h> #include <stdlib.h> #define MAXN 101 long long n; long long a[MAXN]; int cmp(const void* a,const void* b); //´Ó´óµ½Ð¡ int main() { long long i,sum=0; scanf("%lld",&n); for(i=0;i<n;i++) scanf("%lld",a+i); qsort(a,n,sizeof(a[0]),cmp); for(i=1;i<n;i++) { sum += a[i] * a[i-1]; a[i] += a[i-1]; } printf("%lld\n",sum); return 0; } int cmp(const void* a,const void* b) { return *(int *)b - *(int *)a; }
while True: try: n=int(input().strip()) inp=list(map(int,input().strip().split(' '))) #print(inp) inp=sorted(inp) list1=[] while len(inp)!=1: sum1=inp[-1]+inp[-2] mul=inp[-1]*inp[-2] list1.append(mul) inp=inp[:-2]+[sum1] #print(list1) result=sum(list1) print(result) except: break
# 获取输入的数据 n = int(input()) w = list(map(int, input().split())) # 初始化得分为0 score = 0 def cross(w, score): """ 定义一个函数,每次调用都会合并w中最接近的两项 :param w: :param score: :return: """ # if n == 1: # return w, score # 对w的预处理,排序;使得最相近的两数相邻 w = sorted(w) # 求w的极差 gap = max(w)-min(w) # 寻找最相邻的两数也是一个遍历过程,可能的取值从0到极差 for i in range(gap+1): # 从头遍历w中的 每个元素,看它与它的前一项是否符合本轮要找的最相近的两数 for j in range(1, len(w)): if w[j]-w[j-1] == i: # 当找到最相邻的两数时,更新得分 score += w[j]*w[j-1] # w得到两数合并之后的新的成员 w.append(w[j] + w[j - 1]) # 除去旧的成员 w.pop(j) w.pop(j-1) # 只要找到就可以直接推出循环,返回新的w与更新过的score return w, score while True: # 多次调用函数,直到w长度为1时,推出循环 if len(w) == 1: break else: w, score = cross(w, score) print(score)
n=int(input()) L=list(map(int,input().split())) L.sort() s=0 for i in range(n-1): t=L.pop() s+=(t*L[-1]) L[-1]+=t print(s)