NOI Online入門組《文具訂購》詳細題解報告

解法一:80分

分析:

可採用暴力的方法,枚舉圓規和筆的數量。筆記本的數量不要去枚舉,直接計算即可。這樣只需要兩層循環即可。
兩個地方需要注意:一是班費爲0元時需要特別判斷;二是最少可能購買0套,比如班費爲3元時,答案是“0 0 3”。

代碼:

#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("order.in", "r", stdin);
    freopen("order.out", "w", stdout);
#endif

    int n;
    cin >> n;

    if(0 == n)//班費爲0元需要特判
    {
        cout << "0 0 0";
        return 0;
    }

    int lastMin = -1, ansI = 0, ansJ = 0, ansK = 0;
    for(int i = 0; i <= n/7; i++)
    {
        for(int j = 0; j <= n/4; j++)
        {
            int k = (n - 7 * i - 4 * j) / 3;
            if(k >= 0 && n == 7 * i + 4 * j + 3 * k)
            {
                int Min = min(min(i, j), k); //可買多少套
                if(Min > lastMin)
                {
                    lastMin = Min;
                    ansI = i;
                    ansJ = j;
                    ansK = k;
                }
            }
        }
    }

    if(-1 == lastMin)
    {
        cout << -1;
    }
    else
    {
        cout << ansI << ' ' << ansJ << ' ' << ansK;
    }

    return 0;
}

運行結果:

在這裏插入圖片描述

運行超時原因分析:

n的最大值爲10萬,則最多需要循環10萬/7 * 10萬/4 ≈ 3.6億次。運行次數過多導致超時。

解法二:100分

分析:

題目要求a,b,c的最小值儘可能大,所以就要讓它們的最小值越接近n/14。
越好,如果a,b,c的最小值爲n/14時無解,則嘗試最小時爲n/14-1的情景,如果仍然無解,則嘗試最小值爲n/14-2的情景,依此類推。

題目還要求a+b+c儘可能大。因爲c最便宜,所以在成套的基礎上,剩餘的錢若能拆成c就儘量拆成c。若無法拆成c再考慮拆成b。
舉兩個例子:

例1:

若成套購買後還剩餘12元,則12元可買3個b,也可買4個c,顯然買4個c得到的總數量更多。

例2:

若成套購買後還剩餘7元,則12元可買1個a,也可買1個b加上1個c,顯然買1個b加上1個c得到的總數量更多。

代碼:

#include <iostream>
#include <cstdio>
using namespace std;

int main(void)
{
#ifndef ONLINE_JUDGE
    freopen("order.in", "r", stdin);
    freopen("order.out", "w", stdout);
#endif

    int n;
    cin >> n;

    if(0 == n)  //班費爲0元時要特判
    {
        cout<<"0 0 0"<<endl;
        return 0;
    }

    for(int a = n / 14; a >= 0; a--)        //枚舉最小值,即圓規的數量
    {
        for(int b = a; b <= n / 4; b++)      //枚舉筆的數量
        {
            for(int c = a; c <= n / 3; c++) //枚舉筆記本的數量
            {
                if(a * 7 + b * 4 + c * 3 == n)
                {
                    cout << a << " " << b << " " << c << endl;
                    return 0;
                }
            }
        }
    }

    cout << "-1" << endl;   //無解
    return 0;
}
瞭解信息學奧賽請加微信307591841或QQ羣581357582

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