文章目錄
- 題目描述
- 輸入
- 輸出
- 樣例輸入
- 樣例輸出
- C語言代碼實現
- 思路
- 排序
- 處理
- 完整代碼
- C++代碼實現
- 排序
- 完整代碼
- 彩蛋
題目描述
小健有一家自己的商店,主營牛奶飲品,最近資金緊張,他想以盡可能低的價格進購足夠的牛奶以供日常的需要。所以小健想要求助你幫他想出一個最好的節省資金的辦法。
小健可以從幾個農場里購買牛奶,每個農場的牛奶都有自己的價格,每天的供應量也是有限的。小健只可以從每個農場里購買整數量的牛奶,且數量要小于等于農場的最大供應量。
給你小健每天所需要的牛奶總量,以及每個農場牛奶的單價和最大供應量,請你計算一下小健最少花多少錢就可以滿足自己的需求。
ps: 一定存在一個方案可以滿足小健的需求。
輸入
多組輸入,讀入到文件末。
每組的第一行兩個整數N and M.
第一個數 N (0 <= N <= 2000000) 小健每天的牛奶需求量. 第二個數 M (0 <= M <= 5000) 小健可以選擇購買的農場數.
每組的第二行到M+1行:每行兩個整數 Pi and Ai.
Pi (0 <= Pi <= 1000)農場i的牛奶單價.
Ai (0 <= Ai <= 2000000)農場i的最大供應量.
輸出
輸出可以滿足小健每天需求的最小錢數。
樣例輸入
100 5
5 20
9 40
3 10
8 80
6 30
樣例輸出
630
C語言代碼實現
思路
思路其實很簡單,做數學題嘛,先把每個農場的牛奶價格由低到高作升序排列,然后開始看第一個農場有的牛奶總量夠不夠小健的需求,不夠的話再去第二個農場買嘛,直到買夠為止。
拿這道題來講:
1、先做價格的排序(同時仍要將牛奶量與之對應)
3 10
5 20
6 30
8 80
9 40
10+20+30+40=100 也就是買到第四行的時候不必將80個全買下來,買40個就夠了
因此價格就等于10 * 3 + 20 * 5 + 30 * 6 + 40 * 8 = 630
排序
排序難點其實不在于排價格,價格從低到高排列,冒泡啊、插入啊、快排啊、都能解決,難點在于如何將價格排序的同時,將對應農場的牛奶量也進行相應的排序(因為采用的是兩個數組分別存價格和牛奶量),但仔細一想,也不難。排價格數組的時候順便把牛奶量數組的下標一改就行了。代碼如下:
void sort(int* a,int* b) {for(int m = 1; m < M; m++){int t = a[m];int q = b[m];for(int j=m;a[j]<a[j-1];j--){a[j]=a[j-1];a[j-1]=t;b[j]=b[j-1];b[j-1]=q;}}
}
處理
接下來就是簡簡單單的做小學數學題了。代碼如下:
int deal(int N,int* P,int* A) {mon=0;//價格重置for (int i = 0; i < M; i++) {int tmp = N < A[i]? N : A[i];//通過三目運算來擇取剩余需求和農場i牛奶量之間的最小值mon += tmp * P[i];//計算價格N -= tmp;//重新處理剩余需求}return mon;//最終返回所求的最低價格
}
完整代碼
#include <iostream>
#include <vector>
using namespace std;int N,M;//N需求量,M農場數
#define num 5003
int P[num];
int A[num];//P牛奶單價,A最大供應量
int mon;//最低價格int deal(int N,int* P,int* A) {mon=0;//價格重置for (int i = 0; i < M; i++) {int tmp = N < A[i]? N : A[i];//通過三目運算來擇取剩余需求和農場i牛奶量之間的最小值mon += tmp * P[i];//計算價格N -= tmp;//重新處理剩余需求}return mon;
}void sort(int* a,int* b) {for(int m = 1; m < M; m++){int t = a[m];int q = b[m];for(int j=m;a[j]<a[j-1];j--){a[j]=a[j-1];a[j-1]=t;b[j]=b[j-1];b[j-1]=q;}}
}int main(int argc, char const *argv[]) {while (cin >> N >> M) {for (int i = 0; i < M; i++) {cin >> P[i];cin >> A[i];}sort(P,A);deal(N,P,A);cout << mon << endl;}return 0;
}
C++代碼實現
思路都一樣,只是存儲價格和牛奶量的方法不再局限于數組,可以使用容器vector和結構模板pair,以及不用自己實現sort函數,可以直接調用algorithm里的sort函數。(ps:當然c語言也有qsort函數,但是STL是真的香啊~)
排序
寫一個compare函數的目的主要是為了便于自己理解sort函數的第三個參數,當然不寫自定義函數直接將sort的第三個參數寫成lambda表達式會更方便(也更難理解嚶嚶嚶)。哦此處提醒一下,從數學上來看,sort函數是一個左邊閉區間,右邊開區間的域
,也就是如果有一個數組a[3],用戶想要給整個數組升序排序要寫成sort(a,a+3),眾所周知a[3]是a+2,當然用容器就不牽扯這個問題了。
bool compare(pair<int,int> a,pair<int,int> b){return a.first < b.first;//升序排列
}
完整代碼
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int N,M;//N需求量,M農場數
int mon;//最低價格bool compare(pair<int,int> a,pair<int,int> b){return a.first < b.first;
}int main(int argc, char const *argv[]) {while (cin >> N >> M) {vector<pair<int,int>> data(M);//data存儲牛奶單價(first)和最大供應量(second)for (int i = 0; i < M; i++) {cin >> data[i].first >> data[i].second;}sort(data.begin(),data.end(),compare);mon = 0;for (auto& tmp : data) {int num = N > tmp.second? tmp.second : N;mon += (num * tmp.first);N -= num;}cout << mon << endl;}return 0;
}
彩蛋
不需要compare的sort長什么樣呢?我明天就學lambda表達式好叭!
sort(res.begin(), res.end(),[](const pair<int, int>& cast1, const pair<int, int>& cast2){return cast1.first < cast2.first;});