試題 算法訓練 石子游戲
題目描述:
資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
石子游戲的規則如下:
地上有n堆石子,每次操作可選取兩堆石子(石子個數分別爲x和y)並將它們合併,操作的得分記爲(x+1)×(y+1),對地上的石子堆進行操作直到只剩下一堆石子時停止遊戲。
請問在整個遊戲過程中操作的總得分的最大值是多少?
輸入格式
輸入數據的第一行爲整數n,表示地上的石子堆數;第二行至第n+1行是每堆石子的個數。
輸出格式
程序輸出一行,爲遊戲總得分的最大值。
樣例輸入
10
5105
19400
27309
19892
27814
25129
19272
12517
25419
4053
樣例輸出
15212676150
數據規模和約定
1≤n≤1000,1≤一堆中石子數≤50000
解題思路:
把這些數據從大到小排序,每次取最大的兩個,即可,不難實現。
注意:
使用long long類型,不然不夠。
下面提供兩種方法實現,時刻的排序。其中第二種使用優先隊列。
第一種AC代碼:
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
int a[1000];
int main()
{
int n,i;
cin>>n;
long long ans=0;
for(i=0;i<n;i++)
cin>>a[i];
long long max1,max2,pos1,pos2;//注意類型
int t=1;
while(t<n)//執行n-1次即可
{
max1=0;
max2=0;
for(i=0;i<n;i++)//找到最大的那個數字
if(max1<a[i])
{
max1=a[i];
pos1=i;
}
a[pos1]=0;//爲了找到第二大的數字,現將第一次找到的索引位置數值爲0
for(i=0;i<n;i++)//找到第二大的數字
if(max2<a[i])
{
max2=a[i];
pos2=i;
}
ans+=(max1+1)*(max2+1);
a[pos1]+=max1+max2;
a[pos2]=0;
t++;
}
cout<<ans<<endl;
return 0;
}
第二種AC代碼:
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
using namespace std;
int main()
{
//優先隊列,從大到小排序(最先出來的是最小的)
priority_queue<long long,vector<long long>,less<long long> >stones;
long long x,y,ans=0;
int n;
cin>>n;
long long temp;
for(int i=0;i<n;i++)
{
cin>>temp;
stones.push(temp);
}
while(stones.size()>=2)
{
x=stones.top();
stones.pop();
y=stones.top();
stones.pop();
ans+=(x+1)*(y+1);
stones.push(x+y);
}
cout<<ans<<endl;
return 0;
}