解法一: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