UVa506
编写程序实现类似Linux下的软件包管理器,其工作方式为:
- 可以通过命令显式安装组件,这个过程也可能隐式安装依赖组件
- 如果没有其它组件仍然依赖一个隐式安装的组件,则该组件可以通过命令显式的卸载,或者当最后一个依赖该隐式安装的组件的其它组件被卸载时,该组件会被隐式的卸载
- 已经隐式安装的组件不会因为命令的显式安装而转换为显式安装
第2条原文在下面,需要再解释一下。前半句话有问题,没有其它组件仍然依赖一个隐式安装的组件这个状态是不存在的,因为如果这个组件是隐式安装的,同时又不再被别的组件依赖,那么卸载最后一个依赖该组件的其它组件时应该就已经把该组件卸载了。
Likewise, a component, not explicitly installed, can be explicitly removed in response to a command (if it is not needed to support other components) or implicitly removed if it is no longer needed to support another component.
还有两点需要注意:
- 安装和卸载的组件可能是第一次出现的,所以要先添加组件
- 很多博客说输出样例中的
Removing HTML和Removing TCPIP写反了,这其实和卸载依赖的顺序有关系,卸载BROWSER后,是先卸载HTML再卸载TCPIP还是先卸载TCPIP再卸载HTML对是否AC并没有影响,不过我觉得安装的顺序和卸载的顺序应该是相反的
#include <iostream>
#include <algorithm>
#include <list>
#include <map>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
struct Component
{
string name;
size_t idx;
bool explicitly, installed;
vector<size_t> dependent;
list<size_t> InstalledSupport;
Component(const string &name, size_t idx)
: name(name), idx(idx), explicitly(false), installed(false) {}
void AddDependency(const Component &dependency)
{
if (find(dependent.begin(), dependent.end(), dependency.idx) == dependent.end()) {
dependent.push_back(dependency.idx);
}
}
void AddSupport(const Component &support)
{
if (find(InstalledSupport.begin(), InstalledSupport.end(), support.idx) == InstalledSupport.end()) {
InstalledSupport.push_back(support.idx);
}
}
void DelSupport(const Component &support)
{
InstalledSupport.remove(support.idx);
}
};
class Program
{
public:
Program(ostream &os) : os(os) {}
void depend(const string &items)
{
istringstream iss(items);
string ItemName, DependencyName;
iss >> ItemName;
size_t ItemIdx = AddComponent(ItemName);
while (iss >> DependencyName) {
size_t DependencyIdx = AddComponent(DependencyName);
components[ItemIdx].AddDependency(components[DependencyIdx]);
}
}
void install(const string &item)
{
size_t ItemIdx = AddComponent(item);
Component &component = components[ItemIdx];
if (component.installed) {
PrintWithIndent(component.name + " is already installed.");
}
else {
InstallComponent(component, true);
}
}
void remove(const string &item)
{
size_t ItemIdx = AddComponent(item);
Component &component = components[ItemIdx];
if (!component.installed) {
PrintWithIndent(component.name + " is not installed.");
}
else if (!component.InstalledSupport.empty()) {
PrintWithIndent(component.name + " is still needed.");
}
else {
RemoveComponent(component);
}
}
void ListInstalled()
{
for (size_t ComponentIdx : installed)
{
PrintWithIndent(components[ComponentIdx].name);
}
}
private:
vector<Component> components;
map<string, size_t> Name2Idx;
list<size_t> installed;
ostream &os;
size_t AddComponent(const string &item)
{
auto iter = Name2Idx.find(item);
if (iter == Name2Idx.end()) {
Name2Idx[item] = components.size();
components.emplace_back(item, components.size());
return components.back().idx;
}
else return iter->second;
}
void InstallComponent(Component &component, bool explicitly)
{
for (size_t DependencyIdx : component.dependent)
{
Component &dependency = components[DependencyIdx];
if (!dependency.installed) {
InstallComponent(dependency, false);
}
dependency.AddSupport(component);
}
PrintWithIndent("Installing " + component.name);
component.explicitly = explicitly;
component.installed = true;
installed.push_back(component.idx);
}
void RemoveComponent(Component &component)
{
PrintWithIndent("Removing " + component.name);
component.explicitly = false;
component.installed = false;
installed.remove(component.idx);
for (auto riter = component.dependent.rbegin(); riter != component.dependent.rend(); riter++)
{
Component &dependency = components[*riter];
if (dependency.installed) {
if (dependency.InstalledSupport.size() == 1 && !dependency.explicitly) {
RemoveComponent(dependency);
}
dependency.DelSupport(component);
}
}
}
void PrintWithIndent(const string &message)
{
os << " " << message << endl;
}
};
int main()
{
string line;
string command, parameter;
while (getline(cin, line)) {
Program program(cout);
do {
cout << line << endl;
istringstream iss(line);
iss >> command;
if (command == "END") break;
else if (command == "DEPEND") {
getline(iss, parameter);
program.depend(parameter);
}
else if (command == "INSTALL") {
iss >> parameter;
program.install(parameter);
}
else if (command == "REMOVE") {
iss >> parameter;
program.remove(parameter);
}
else if (command == "LIST") {
program.ListInstalled();
}
else;
} while (getline(cin, line));
}
return 0;
}
/*
DEPEND TELNET TCPIP NETCARD
DEPEND TCPIP NETCARD
DEPEND DNS TCPIP NETCARD
DEPEND BROWSER TCPIP HTML
INSTALL NETCARD
INSTALL TELNET
INSTALL foo
REMOVE NETCARD
INSTALL BROWSER
INSTALL DNS
LIST
REMOVE TELNET
REMOVE NETCARD
REMOVE DNS
REMOVE NETCARD
INSTALL NETCARD
REMOVE TCPIP
REMOVE BROWSER
REMOVE TCPIP
END
*/
本文介绍了一个模拟Linux环境下软件包管理器的程序实现。该程序能够处理组件的依赖关系,并支持组件的安装与卸载操作。通过具体的命令实例展示了如何使用该程序进行操作。
1202

被折叠的 条评论
为什么被折叠?



