文章目錄
1. 題目描述
1.1. Limit
Time Limit: 1000 ms
Memory Limit: 131072 kB
1.2. Problem Description
小偉報名參加中央電視臺的智力大沖浪節目。本次挑戰賽吸引了衆多參賽者,主持人爲了表彰大家的勇氣,先獎勵每個參賽者元。先不要太高興!因爲這些錢還不一定都是你的?!接下來主持人宣佈了比賽規則:
首先,比賽時間分爲個時段,它又給出了很多小遊戲,每個小遊戲都必須在規定期限前完成。如果一個遊戲沒能在規定期限前完成,則要從獎勵費元中扣去一部分錢,爲自然數,不同的遊戲扣去的錢是不一樣的。現在你要設計方法,使得你能得到最多的獎勵。
1.3. Input
輸入共 4 行
第 1 行爲 ,表示一開始獎勵給每位參賽者的錢;
第 2 行爲 ,表示有 個小遊戲;
第 3 行有 個數,分別表示遊戲 1 到 的規定完成期限;
第 4 行有 個數,分別表示遊戲 1 到 不能在規定期限前完成的扣款數。
1.4. Output
輸出文件僅 1 行。表示小偉能贏取最多的錢。
1.5. Sample Input
10000
7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
1.6. Sample Output
9950
1.7. Source
2. 解讀
若存在規定完成期限 相同的任務,則可能會出現懲罰。
若有數字,滿足 且在所有任務的完成期限中沒有出現,那麼 對完成期限 的任務 ,即使出現了一次重複,也可以使用 這個時間來完成。
若任務 的截止時間 前不存在沒有出現的數字,或 被 之前出現的重複任務消耗掉了,那麼懲罰出現。
懲罰的最優選擇方案爲,將所有任務按照懲罰金額從小到大排序,選擇第一個符合截止時間 條件的任務接受懲罰。即將現有金額 減去 。
對所有規定完成期限 相同的任務進行處理以後,即可求得答案。
3. 代碼
#include <iostream>
#include <map>
#include <math.h>
#include <string.h>
using namespace std;
// 記錄最晚完成時間
long long timeList[500];
// 記錄懲罰
long long penalty[500];
// 記錄出現次數
long long countTime[500];
// 時間到懲罰的映射
multimap<long long, long long> timeToPenalty;
// map指針
multimap<long long, long long>::iterator iter;
// 將前面輪空的time次數存儲起來
long long storage;
int main()
{
long long m, n, maxTime;
// 讀入m
scanf("%lld", &m);
// 讀入n
scanf("%lld", &n);
// 初始化數組
memset(timeList, 0, sizeof(timeList));
memset(penalty, 0, sizeof(penalty));
memset(countTime, 0, sizeof(countTime));
// 初始化最大值
maxTime = 0;
// 初始化存儲
storage = 0;
// 存儲時間
for (long long i = 0; i < n; i++) {
// 讀入時間
scanf("%lld", &timeList[i]);
// 存儲時間的出現次數
countTime[timeList[i]]++;
// max
maxTime = max(maxTime, timeList[i]);
}
// 存儲懲罰
for (long long i = 0; i < n; i++) {
// 讀入懲罰
scanf("%lld", &penalty[i]);
// 存入map
timeToPenalty.insert(make_pair(penalty[i], timeList[i]));
}
// 判斷是否有重複元素
for (long long i = 1; i <= maxTime; i++) {
// 先消耗存儲
if (countTime[i] > 1 && storage > 0) {
int countMark = countTime[i] - 1;
for (int j = 0; j < countMark; j++) {
countTime[i]--;
storage--;
if (storage <= 0) {
break;
}
}
}
// 若有重複時間
if (countTime[i] > 1) {
// 將penalty從小到大進行遍歷
for (iter = timeToPenalty.begin(); iter != timeToPenalty.end(); iter++) {
// 若符合條件
if (iter->second <= i && iter->second != -1) {
// 減去penalty
m -= iter->first;
// 將已經減去的penalty清除
iter->second = -1;
// countTime-1
countTime[i]--;
if (countTime[i] <= 1) {
// 退出循環
break;
}
}
}
} else if (countTime[i] == 0) {
// 若有time輪空,存儲起來
storage++;
}
}
// 輸出
printf("%lld", m);
}
聯繫郵箱:[email protected]
Github:https://github.com/CurrenWong
歡迎轉載/Star/Fork,有問題歡迎通過郵箱交流。