JZOJ 1736. 撲克遊戲 (Standard IO)

1736. 撲克遊戲 (Standard IO)

Time Limits: 1000 ms Memory Limits: 128000 KB

Description

  有一棵無窮大的滿二叉樹,根爲star,其餘所有點的權值爲點到根的距離,如圖:
  這裏寫圖片描述
  現在你有一些撲克牌,點數從1到13,你要把這些撲克牌全部放到這個樹上:
  1. 當你把點數爲i的撲克牌放在權值爲j的點上,那麼你會得到i*j的分數。
  2. 當你把一個撲克牌放在一個節點上,那麼你就不能把別的撲克牌放在這個節點以及這個節點的子樹上。
  你的目標是最小化你的得分。

Input

  文件名爲 poker.in
  輸入第一行爲一個數字N,表示你有的撲克牌數;
  接下來一行N個數字,數字在1到13之間。

Output

  文件名爲 poker.out
  一個數字,最小得分。

Sample Input

3
5 10 13

Sample Output

43

Data Constraint

Hint

【樣例說明】
  這裏寫圖片描述
【數據範圍】
  30%數據 N<=100
  100%數據滿足1<=N<=10000.

題解

這是今天做的第四道哈夫曼樹專題了
總結一下
解法大同小異,只是換個方式問而已

類似這道題,題目說得分是 i * j 其實就是哈夫曼樹,模型轉換一下就好了

代碼

#include<iostream>
#include<iostream>
#include<cstdio>
#define INF 2147483647
#define N 20000
using namespace std;

long long dui[N*2+1],top;
void add(long x)
{   long now;
    dui[++top]=x;
    for(now=top;dui[now/2]>dui[now]&&now>1;now/=2)
        swap(dui[now],dui[now/2]);
}
long qu()
{   long ans=dui[1],now;
    bool t=false;
    dui[1]=INF;
    now=1;
    while(!t){
        t=true;
        if(now*2==top||dui[now*2]<dui[now*2+1]){
            if(dui[now]>dui[now*2]){
                swap(dui[now],dui[now*2]);
                now=now*2;
                t=false;
            }
        }else if(now*2+1<=top)
            if(dui[now]>dui[now*2+1]){
                swap(dui[now],dui[now*2+1]);
                now=now*2+1;
                t=false;
            }
    }
    return ans;
}

int main()
{   long n,m,i,q;
    long long ans=0;
    scanf("%ld",&n);
    for(i=1;i<=n;i++){
        scanf("%ld",&q);
        add(q);
    }
    for(i=1;i<n;i++){
        q=qu()+qu();
        ans+=q;
        add(q);
    }
    printf("%lld\n",ans);
    return 0;
}

ps:
看過我其他博文的有沒有感覺代碼很熟悉
沒錯,就是合併果子

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章