申請SAE

如果您發現本博客的外觀很難看,那是因為部分外觀文件被中國.國家.防火.牆屏.蔽所致!
請翻~牆!

我的Wordpress博客的地址: http://zhuyf.tk/

2011年10月25日 星期二

NOIP2007普及組 紀念品分組 解題報告

【題目描述】
元旦快到了,校學生會讓樂樂負責新年晚會的紀念品發放工作。爲使得參加晚會的同學所獲得的紀念品價值相對均衡,他要把購來的紀念品根據價格進行分組,但每 組最多只能包括兩件紀念品,並且每組紀念品的價格之和不能超過一個給定的整數。爲了保證在儘量短的時間內發完所有紀念品,樂樂希望分組的數目最少。
你的任務是寫一個程序,找出所有分組方案中分組數最少的一種,輸出最少的分組數目。

【輸入】
輸入文件group.in包含n+2行:
第1行包括一個整數w,爲每組紀念品價格之和的上限。
第2行爲一個整數n,表示購來的紀念品的總件數。
第3~n+2行每行包含一個正整數pi(5<=pi<=w),表示所對應紀念品的價格。

【輸出】
輸出文件group.out僅一行,包含一個整數,即最少的分組數目。

【輸入樣例】
100
9
90
20
20
30
50
60
70
80
90

【輸出樣例】
6

【限制】
50%的數據滿足:l<=n<=15
100%的數據滿足:1<=n<=30000,80<=w<=200

【分析】
貪心策略,先排序,可以用快排、堆排、插入排序、甚至桶排序,每次找到最小的價格Min和最大的價格Max,如果Max+Min>W,則有最大價格的那個物品單獨成一組,然後更新Max;如果Max+Min<=W,則把這兩件物品分為一組,然後更新Min和Max。

【參考程序】
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
int num[30001];
int Max=0,Min=0xfffffff;
int Group=0;
int W,G;

int Cmp(const void *a,const void *b)
{
    return *((int *)a)-*((int *)b);
}

void init()
{
    scanf("%d\n%d",&W,&G);
    for (int i=1;i<=G;i++)
        scanf("%d",&num[i]);
    qsort(num+1,G,sizeof(num[0]),Cmp);
}

void Greedy()
{
    int q=1,h=G;
    while (q<=h)
    {
        if (q==h)
        {
            Group++;
            return;
        }
        else
        {
            if (num[q]+num[h]>W)
            {
                Group++;
                h--;
            }
            else
            {
                Group++;
                q++;
                h--;
            }
        }
    }  
}

void Print()
{
    for (int i=1;i<=G;i++)
        cout<<num[i]<<" ";
}

int main()
{
    freopen("group.in","r",stdin);
    freopen("group.out","w",stdout);
    init();
    Greedy();
    cout<<Group<<endl;
    return 0;
}

沒有留言:

張貼留言