zoukankan      html  css  js  c++  java
  • 【STL+模拟】UVa 506

    System Dependencies 

    Components of computer systems often have dependencies--other components that must be installed before they will function properly. These dependencies are frequently shared by multiple components. For example, both the TELNET client program and the FTP client program require that the TCP/IP networking software be installed before they can operate. If you install TCP/IP and the TELNET client program, and later decide to add the FTP client program, you do not need to reinstall TCP/IP.


    For some components it would not be a problem if the components on which they depended were reinstalled; it would just waste some resources. But for others, like TCP/IP, some component configuration may be destroyed if the component was reinstalled.


    It is useful to be able to remove components that are no longer needed. When this is done, components that only support the removed component may also be removed, freeing up disk space, memory, and other resources. But a supporting component, not explicitly installed, may be removed only if all components which depend on it are also removed. For example, removing the FTP client program and TCP/IP would mean the TELNET client program, which was not removed, would no longer operate. Likewise, removing TCP/IP by itself would cause the failure of both the TELNET and the FTP client programs. Also if we installed TCP/IP to support our own development, then installed the TELNET client (which depends on TCP/IP) and then still later removed the TELNET client, we would not want TCP/IP to be removed.


    We want a program to automate the process of adding and removing components. To do this we will maintain a record of installed components and component dependencies. A component can be installed explicitly in response to a command (unless it is already installed), or implicitly if it is needed for some other component being installed. 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. Installing an already implicitly-installed component won't make that component become explicity installed.

    Input 

    The input will contain a sequence of commands (as described below), each on a separate line containing no more than eighty characters. Item names are case sensitive, and each is no longer than ten characters. The command names (DEPENDINSTALLREMOVE and LIST) always appear in uppercase starting in column one, and item names are separated from the command name and each other by one or more spaces. All appropriate DEPENDcommands will appear before the occurrence of any INSTALL command that uses them. There will be no circular dependencies. The end of the input is marked by a line containing only the word END.

    Command Syntax Interpretation/Response
    DEPEND item1 item2 [item3 ...] item1 depends on item2 (and item3 ...)
    INSTALL item1 install item1 and those on which it depends
    REMOVE item1 remove item1, and those on which it depends, if possible
    LIST list the names of all currently-installed components

    Output 

    Echo each line of input. Follow each echoed INSTALL or REMOVE line with the actions taken in response, making certain that the actions are given in the proper order. Also identify exceptional conditions (see Sample Output, below, for examples of all cases). For the LIST command, display the names of the currently installed components in the installation order. No output, except the echo, is produced for a DEPEND command or the line containing END. There will be at most one dependency list per item.

    Sample Input 1 

    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

    Sample Output 1 

    DEPEND   TELNET TCPIP NETCARD
    DEPEND TCPIP NETCARD
    DEPEND DNS TCPIP NETCARD
    DEPEND  BROWSER   TCPIP  HTML
    INSTALL NETCARD
       Installing NETCARD
    INSTALL TELNET
       Installing TCPIP
       Installing TELNET
    INSTALL foo
       Installing foo
    REMOVE NETCARD
       NETCARD is still needed.
    INSTALL BROWSER
       Installing HTML
       Installing BROWSER
    INSTALL DNS
       Installing DNS
    LIST
       NETCARD
       TCPIP
       TELNET
       foo
       HTML
       BROWSER
       DNS
    REMOVE TELNET
       Removing TELNET
    REMOVE NETCARD
       NETCARD is still needed.
    REMOVE DNS
       Removing DNS
    REMOVE NETCARD
       NETCARD is still needed.
    INSTALL NETCARD
       NETCARD is already installed.
    REMOVE TCPIP
       TCPIP is still needed.
    REMOVE BROWSER
       Removing BROWSER
       Removing HTML
       Removing TCPIP
    REMOVE TCPIP
       TCPIP is not installed.
    END

    Sample Input 2 

    DEPEND A B
    INSTALL A
    INSTALL B
    REMOVE A
    END

    Sample Output 2 

    DEPEND A B
    INSTALL A
       Installing B
       Installing A
    INSTALL B
       B is already installed.
    REMOVE A
       Removing A
       Removing B
    END


    前话:虽然划归到数据结构这一章,但还是一个需要熟练使用STL的模拟题;说实话代码是按照如家大神的思路来的,而且如果不看他的思路的话自己的条理也应该不会这么清晰吧...总之又学到了新的思路。学一点就得记住一点啊。

    题意:软件组件之间会有依赖关系,比如你下一个Codeblocks你也得顺带着把编译器给下上。你的任务是模拟安装和卸载软件组件的过程。有以下五种指令,如果指令为“END”则退出程序;若为以下四种指令,则分别作对应操作:
    Command Syntax Interpretation/Response
    DEPEND item1 item2 [item3 ...] item1 depends on item2 (and item3 ...)
    INSTALL item1 install item1 and those on which it depends
    REMOVE item1 remove item1, and those on which it depends, if possible
    LIST list the names of all currently-installed components
    在INSTALL指令中提到的组件成为显示安装,这些组件必须用REMOVE指令显示删除。同样,被显示安装的组件直接或间接依赖的其他组件也不能在REMOVE指令中删除。
    最后就是注意字符串输入与输出的细节问题。

    分析:
    ①输入问题:
    注意输入的语句需要同一格式输出,所以需要用getline输入,对于语句中会出现空白符且需要提取子串,这里可以用到istringstream类(头文件sstream),其功能为从流中提取数据,支持>>操作,用法为:
     1 #include<iostream>
     2 #include<sstream>
     3 using namespace std;
     4 int main()
     5 {
     6     string str, line;
     7     while(getline(cin, line))
     8     {
     9         istringstream stream(line);
    10         while(stream>>str)
    11             cout<<str.c_str()<<endl;
    12     }    
    13     return 0;
    14 }
    ②细节问题:
    首先,维护一个组建的名字列表——可以把输入中的组件名全部转化为整数编号。此处可以使用一个map记录出现过的组件名及其编号,使用字符串数组name方便记录编号对应的组件名。
    1 int cnt;
    2 int ID(string It)
    3 {
    4     if(item.count(It)) return item[It];
    5     item[It] = ++cnt;
    6     name[cnt] = It;
    7     return cnt;
    8 }
    接下来用两个vector数组depend[x]和be_depended[x]分别表示组件x所依赖的组件列表依赖于x的组件列表。这样就可以方便安装及删除组件。
     1 if(com == "DEPEND")
     2 {
     3     line >> item1;
     4     int id1 = ID(item1), id2;
     5     while(line >> other)
     6     {
     7         id2 = ID(other);
     8         depend[id1].push_back(id2);
     9         be_depended[id2].push_back(id1);
    10     }
    11 }
    为了区别显示安装还是隐式安装,需要一个status[x]数组,0表示组件x未安装,1表示显示安装,2表示隐式安装。
     1 void install(int it, bool toplevel) //toplevel区分显、隐示安装
     2 {
     3     if(!status[it]) //status[x] = 0,组件x未安装
     4     {
     5         for(int i = 0; i < depend[it].size(); i++)
     6         {
     7             install(depend[it][i], false); //所有依赖组件隐式安装,递归调用
     8         }
     9         cout << "   Installing " << name[it] << endl;
    10         status[it] = toplevel ? 1 : 2;
    11         installed.push_back(it); //把已安装的组件加入到vector数组installed中
    12     }
    13 }
    1 if(com == "INSTALL")
    2 {
    3     line >> item1;
    4     int id = ID(item1);
    5     if(status[id]) //若该组件已安装
    6         cout << "   " << name[id] << " is already installed." << endl;
    7     else
    8         install(id, true); //显式安装
    9 }
    而对于删除组件,首先判断组件能否删除,即是否被未删除的组件依赖,若能删除,在删除后再递归删除他所依赖的组件。
     1 bool needed(int it)
     2 {
     3     for(int i = 0; i < be_depended[it].size(); i++)
     4     {
     5         if(status[be_depended[it][i]]) return true; //组件被未删除组件依赖,
     6     }
     7     return false;
     8 }
     9 
    10 void Remove(int it, bool toplevel)
    11 {
    12     if((toplevel || status[it] == 2) && !needed(it))//若该组件显式卸载或它是隐身安装的,且不被依赖,则可以卸载
    13     {
    14         status[it] = 0;
    15         installed.erase( remove(installed.begin(), installed.end(), it), installed.end() ); //注意erase与remove结合的用法
    16         cout << "   Removing " << name[it] << endl;
    17         for(int i = 0; i < depend[it].size(); i++)
    18         {
    19             Remove(depend[it][i], false);
    20         }
    21     }
    22 }
    剩下的就是小意思了,LIST指令直接按编号输出name[]元素就好;

    AC代码如下:
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<vector>
      6 #include<string>
      7 #include<map>
      8 #include<set>
      9 #include<algorithm>
     10 #include<cctype>
     11 #include<sstream>
     12 using namespace std;
     13 
     14 const int maxn = 10000010;
     15 vector<int> depend[maxn], be_depended[maxn];
     16 vector<int> installed;
     17 map<string, int> item;
     18 string name[maxn];
     19 int status[maxn];
     20 int cnt;
     21 int ID(string It)
     22 {
     23     if(item.count(It)) return item[It];
     24     item[It] = ++cnt;
     25     name[cnt] = It;
     26     return cnt;
     27 }
     28 
     29 void install(int it, bool toplevel)
     30 {
     31     if(!status[it]) //status[x] = 0,组件x未安装;status[x] = 1,显示安装;status[x] = 2,隐式安装;
     32     {
     33         for(int i = 0; i < depend[it].size(); i++)
     34         {
     35             install(depend[it][i], false); //隐式安装
     36         }
     37         cout << "   Installing " << name[it] << endl;
     38         status[it] = toplevel ? 1 : 2;
     39         installed.push_back(it);
     40     }
     41 }
     42 
     43 bool needed(int it)
     44 {
     45     for(int i = 0; i < be_depended[it].size(); i++)
     46     {
     47         if(status[be_depended[it][i]]) return true; //组件被其他组件依赖,
     48     }
     49     return false;
     50 }
     51 
     52 void Remove(int it, bool toplevel)
     53 {
     54     if((toplevel || status[it] == 2) && !needed(it))
     55     {
     56         status[it] = 0;
     57         installed.erase( remove(installed.begin(), installed.end(), it), installed.end() ); ///!!
     58         cout << "   Removing " << name[it] << endl;
     59         for(int i = 0; i < depend[it].size(); i++)
     60         {
     61 //            cout << name[depend[it][i]] << endl;
     62             Remove(depend[it][i], false);
     63         }
     64     }
     65 }
     66 
     67 int main()
     68 {
     69     //freopen("in.txt", "r", stdin);
     70     cnt = 0;
     71     string com, item1, other;
     72     getline(cin, com);
     73     while(1)
     74     {
     75         cout << com << endl;
     76         istringstream line(com);
     77         line >> com;
     78         //cout << com << endl;
     79         if(com == "END") break;
     80         if(com == "DEPEND")
     81         {
     82             line >> item1;
     83             int id1 = ID(item1), id2;
     84             while(line >> other)
     85             {
     86                 id2 = ID(other);
     87                 depend[id1].push_back(id2);
     88                 be_depended[id2].push_back(id1);
     89             }
     90         }
     91         else if(com == "INSTALL")
     92         {
     93             line >> item1;
     94             int id = ID(item1);
     95             if(status[id])
     96                 cout << "   " << name[id] << " is already installed." << endl;
     97             else
     98                 install(id, true); //显式安装
     99         }
    100         else if(com == "REMOVE")
    101         {
    102             line >> item1;
    103             int id = ID(item1);
    104             if(!status[id])
    105                 cout << "   " << name[id] << " is not installed." << endl;
    106             else if(needed(ID(item1)))
    107                 cout << "   " << name[id] << " is still needed." << endl;
    108             else
    109                 Remove(id, true);  //显式卸载
    110         }
    111         else if(com == "LIST")
    112         {
    113             for(int i = 0; i < installed.size(); i++)
    114                 cout << "   " << name[installed[i]] << endl;
    115         }
    116         getline(cin, com);
    117     }
    118     return 0;
    119 }
    View Code
     
  • 相关阅读:
    关于面试总结8-http协议相关面试题
    关于面试总结7-linux篇
    关于面试总结6-SQL经典面试题
    关于面试总结5-python笔试题(递归)
    关于面试总结4-python笔试题
    关于面试总结3-SQL查询
    关于面试总结2-SQL学生表
    关于面试总结1-SQL学生表
    浅谈多变量线性回归中的数据规范化
    浅谈KL散度
  • 原文地址:https://www.cnblogs.com/LLGemini/p/4337087.html
Copyright © 2011-2022 走看看