zoukankan      html  css  js  c++  java
  • UVa 506 System Dependencies (细节问题)

    题意:输入几种指令,让你进行模拟操作,指令如下:

    DEPEND item1 item2 (item3 ...) 安装item1需要先安装item2(、item3……)
    INSTALL item1 安装item1,如果item1依赖其他组件,则先安装其依赖的其他组件(如果已经安装就不用安装了)
    REMOVE item1 移除item1及其依赖的全部组件,如果组件被其他程序依赖,则不移除
    LIST 输出当前已安装的所有组件
    END 结束程序

    析:看到这个题,虽然是放在数据结构这一章里,没觉得有什么数据结构的东西,算法上并不难,只是操作麻烦一点,又是调了好长时间,开始用的1024vector,

    RE了,后来我加大了10倍,还有的是后来我看到网上样例不一样都过了,很明显是我没读懂题意,可能移除时顺序是无所谓的。

    首先需要的是把每个名字转化成一个id数,我用了两个map,其实可以不用的,那么时间复杂度可能高一点,然后要两个vector,一个存所依赖的组件,一个存依赖于的组件列表。

    然后还要用一个数组来记录未安装,还是隐式安装,还是显示安装。安装删除时用递归实现较好。

    主要注意以下几点:

      输出比较麻烦,如果已经安装过的显式安装,要输出已经安装了,隐式的直接忽略。

      如果要删除显式安装,除了本身,那么要输出仍然需要。

      如果要删除一个不存在的显式安装,要输出没有安装。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <sstream>
    #include <map>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 10240;
    vector<int> v1[maxn];
    vector<int> v2[maxn];
    vector<int> is_install;
    map<string, int> mp;
    map<int, string> item;
    int cnt = 0;
    int status[maxn];//0表示未安装,1表示隐式安装,2表示显式安装
    
    int getid(const string &s){//获得id
        if(mp.count(s))  return mp[s];
        mp[s] = ++cnt;
        item[cnt] = s;
        return cnt;
    }
    
    void install(int t, bool ok){
        if(status[t] && ok){  cout << "   " << item[t] << " is already installed.
    ";  return ; }//已经安装过的显式安装,要输出已经安装了
        if(status[t])  return ;//隐式安装,忽略
    
        for(int i = 0; i < v1[t].size(); ++i)
            install(v1[t][i], false);//递归查找安装
        cout << "   Installing " << item[t] << endl;
        status[t] = ok ? 1 : 2;//确定是隐式安装还是显式安装
        is_install.push_back(t);
    }
    
    bool need(int t){
        for(int i = 0; i < v2[t].size(); ++i)
            if(status[v2[t][i]])  return true;//这个地方我刚开始写的是 2 == status[v2[t][i]],
            //结果不对,因为首先在存储时就已经确定了,存入的都是显式安装的,并不用重新判定,
            //只要判定是不是移除了就好,另外的是在安装时实验它的状态可能会改变,所以不能这么写
        return false;
    }
    
    void remove1(int t, bool ok){
        if(ok && !status[t]){  cout << "   " << item[t] << " is not installed.
    ";  return ; }//删除一个不存在的显式安装,要输出没有安装。
    
        if((ok || status[t] == 2) && !need(t)){
            status[t] = 0;
            is_install.erase(remove(is_install.begin(), is_install.end(), t), is_install.end());//remove不是真删除元素,而是把它们放到后面去,并返回地扯
            cout << "   Removing " << item[t] << endl;
            for(int i = v1[t].size()-1; i >= 0; --i)//这个地方如果从0开始也对,应该是我没读懂题意吧
                remove1(v1[t][i], false);
            return ;
        }
        if(ok) cout << "   " << item[t] << " is still needed.
    ";//删除显式安装,除了本身,那么要输出仍然需要。
    }
    
    int main(){
    //    freopen("in.txt", "r", stdin);
        string s;
        memset(status, 0, sizeof(status));
        while(getline(cin, s)){
            cout << s << endl;
            if(s == "END")  break;
            stringstream ss(s);
            string s1, s2;
            ss >> s1;
            if('D' == s1[0]){
                ss >> s2;
                int t = getid(s2);
                while(ss >> s){  v1[t].push_back(getid(s));  v2[getid(s)].push_back(t);  }
            }
            else if('I' == s1[0]){
                while(ss >> s2)  install(getid(s2), true);
            }
            else if('R' == s1[0]){
                ss >> s2;  remove1(getid(s2), true);
            }
            else if('L' == s1[0]){
                for(int i = 0; i < is_install.size(); ++i)
                    cout << "   " << item[is_install[i]] << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    485串口接线
    mvc3 升级mvc5
    VB连接ACCESS数据库,使用 LIKE 通配符问题
    VB6 读写西门子PLC
    可用的 .net core 支持 RSA 私钥加密工具类
    解决 Win7 远程桌面 已停止工作的问题
    解决 WinForm 重写 CreateParams 隐藏窗口以后的显示问题
    解决安装 .net framework 发生 extracting files error 问题
    CentOS7 安装配置笔记
    通过特殊处理 Resize 事件解决 WinForm 加载时闪烁问题的一个方法
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5591986.html
Copyright © 2011-2022 走看看