题目描述
静态扫描可以快速识别源代码的缺陷,静态扫描的结果以扫描报告作为输出:
1、文件扫描的成本和文件大小相关,如果文件大小为N,则扫描成本为N个金币
2、扫描报告的缓存成本和文件大小无关,每缓存一个报告需要M个金币
3、扫描报告缓存后,后继再碰到该文件则不需要扫描成本,直接获取缓存结果
给出源代码文件标识序列和文件大小序列,求解采用合理的缓存策略,最少需要的金币数。
输入描述
第一行为缓存一个报告金币数M,L<= M <= 100
第二行为文件标识序列:F1,F2,F3,....,Fn。
第三行为文件大小序列:S1,S2,S3,....,Sn。
备注:
- 1 <= N <= 10000
- 1 <= Fi <= 1000
- 1 <= Si <= 10
输出描述
采用合理的缓存策略,需要的最少金币数
用例
输入 | 5 1 2 2 1 2 3 4 1 1 1 1 1 1 1 |
输出 | 7 |
说明 | 文件大小相同,扫描成本均为1个金币。缓存任意文件均不合算,因而最少成本为7金币。 |
输入 | 5 2 2 2 2 2 5 2 2 2 3 3 3 3 3 1 3 3 3 |
输出 | 9 |
说明 | 无 |
题目解析
问题描述
静态扫描可以快速识别源代码的缺陷,扫描结果以报告的形式输出。扫描一个文件的成本与文件大小有关,文件大小为N,则扫描成本为N个金币。缓存扫描报告的成本固定为M个金币,如果以后再读取该文件则可以直接读取缓存报告,成本为M个金币。
需要给出源代码文件标识序列和文件大小序列,求解采用合理的缓存策略,使得需要的最少金币数。
输入描述
- 第一行输入一个报告金币数M,1 <= M <= 100。
- 第二行输入文件标识序列F1, F2, ..., Fn。
- 第三行输入文件大小序列S1, S2, ..., Sn。
- 1 <= N <= 10000
- 1 <= Fi <= 1000
- 1 <= Si <= 10
输出描述
采用合理的缓存策略,所需的最少金币数。
示例
输入:
5
1 2 2 1 2 3 4
1 1 1 1 1 1 1
输出:
7
解题思路
- 扫描与缓存成本比较:对于每个文件,判断是重新扫描成本低还是使用缓存成本低。
- 动态规划:维护一个最少成本数组,依次计算每个文件的最少成本。
- 缓存策略:使用缓存时更新缓存状态。
C++代码实现
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
int main() {
int M;
cin >> M;
vector<int> file_identifiers;
vector<int> file_sizes;
int temp;
while (cin >> temp) {
file_identifiers.push_back(temp);
if (cin.peek() == '\n') break;
}
for (int i = 0; i < file_identifiers.size(); ++i) {
cin >> temp;
file_sizes.push_back(temp);
}
unordered_map<int, int> last_scan;
int total_cost = 0;
for (int i = 0; i < file_identifiers.size(); ++i) {
int file_id = file_identifiers[i];
int file_size = file_sizes[i];
if (last_scan.find(file_id) == last_scan.end()) {
total_cost += file_size;
last_scan[file_id] = i;
} else {
int last_index = last_scan[file_id];
int rescan_cost = file_size;
int cache_cost = M;
if (cache_cost < rescan_cost) {
total_cost += cache_cost;
} else {
total_cost += rescan_cost;
}
last_scan[file_id] = i;
}
}
cout << total_cost << endl;
return 0;
}
代码说明
- 读取输入:读取缓存成本M,文件标识序列和文件大小序列。
- 维护最少成本:使用unordered_map记录每个文件上次扫描的位置,如果当前文件已经扫描过,比较缓存成本和重新扫描成本,选择最小的。
- 输出结果:输出采用合理缓存策略的最少金币数。
这个程序能够计算出在合理的缓存策略下所需的最少金币数。
python代码实现
def min_cost_to_scan(M, file_identifiers, file_sizes):
last_scan = {}
total_cost = 0
for i in range(len(file_identifiers)):
file_id = file_identifiers[i]
file_size = file_sizes[i]
if file_id not in last_scan:
total_cost += file_size
last_scan[file_id] = i
else:
rescan_cost = file_size
cache_cost = M
if cache_cost < rescan_cost:
total_cost += cache_cost
else:
total_cost += rescan_cost
last_scan[file_id] = i
return total_cost
# 读取输入
M = int(input().strip())
file_identifiers = list(map(int, input().split()))
file_sizes = list(map(int, input().split()))
# 计算并输出最少金币数
print(min_cost_to_scan(M, file_identifiers, file_sizes))
代码说明
- min_cost_to_scan函数:实现了计算最少金币数的逻辑。使用字典记录每个文件上次扫描的位置,如果当前文件已经扫描过,比较缓存成本和重新扫描成本,选择最小的。
- 读取输入:通过
input().split()
读取一行输入,并转换为整数列表。 - 计算并输出最少金币数:调用
min_cost_to_scan
函数计算最少金币数,并输出结果。
这个Python程序能够计算出在合理的缓存策略下所需的最少金币数。你可以在Python环境中运行这个程序来实现该功能。