刷紫书第五章例题(例题5-1到5-7)

除了下面的练习外,更多练习:训练题一(C++STL)

例题5-1 Where is the Marble? UVA - 10474

Raju and Meena love to play with Marbles. They have got a lot of
marbles with numbers written on them. At the beginning, Raju would
place the marbles one after another in ascending order of the numbers
written on them. Then Meena would ask Raju to find the first marble
with a certain number. She would count 1…2…3. Raju gets one point
for correct answer, and Meena gets the point if Raju fails. After some
fixed number of trials the game ends and the player with maximum
points wins. Today it’s your chance to play as Raju. Being the smart
kid, you’d be taking the favor of a computer. But don’t underestimate
Meena, she had written a program to keep track how much time you’re
taking to give all the answers. So now you have to write a program,
which will help you in your role as Raju.
Input
There can be multiple test cases. Total no of test cases is less than 65. Each test case consists begins
with 2 integers: N the number of marbles and Q the number of queries Mina would make. The next
N lines would contain the numbers written on the N marbles. These marble numbers will not come
in any particular order. Following Q lines will have Q queries. Be assured, none of the input numbers
are greater than 10000 and none of them are negative.
Input is terminated by a test case where N = 0 and Q = 0.
Output
For each test case output the serial number of the case.
For each of the queries, print one line of output. The format of this line will depend upon whether
or not the query number is written upon any of the marbles. The two different formats are described
below:
• ‘x found at y’, if the first marble with number x was found at position y. Positions are numbered
1, 2, … , N.
• ‘x not found’, if the marble with number x is not present.
Look at the output for sample input for details.
Sample Input
4 1
2
3
5
1
5
5 2
1
3
3
3
1
2
3
0 0
Sample Output
CASE# 1:
5 found at 4
CASE# 2:
2 not found
3 found at 3

知识点:sort,lower_bound(所找数组必须是升序)
AC代码:

#include
#include

using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    int n,q,kase=0;
    int a[100000];
    while(cin>>n>>q && !(n==0 && q==0)){
        cout<<"CASE# "<<++kase<<":"<for(int i=0;icin>>a[i];
        sort(a,a+n);
        int tmp;
        while(q--){
            cin>>tmp;
            int loc=lower_bound(a,a+n,tmp)-a;
            if(a[loc]==tmp)
                cout<" found at "<1<else
                cout<" not found"<return 0;
}

例题5-2 The Blocks Problem UVA - 101

Many areas of Computer Science use simple, abstract domains for both analytical and empirical studies.
For example, an early AI study of planning and robotics (STRIPS) used a block world in which a robot
arm performed tasks involving the manipulation of blocks.
In this problem you will model a simple block world under certain rules and constraints. Rather
than determine how to achieve a specified state, you will “program” a robotic arm to respond to a
limited set of commands.
The problem is to parse a series of commands that instruct a robot arm in how to manipulate blocks
that lie on a flat table. Initially there are n blocks on the table (numbered from 0 to n − 1) with block
bi adjacent to block bi+1 for all 0 ≤ i < n − 1 as shown in the diagram below:
Initial Blocks World
The valid commands for the robot arm that manipulates blocks are:
这里写图片描述
• move a onto b
where a and b are block numbers, puts block a onto block b after returning any blocks that are
stacked on top of blocks a and b to their initial positions.
• move a over b
where a and b are block numbers, puts block a onto the top of the stack containing block b, after
returning any blocks that are stacked on top of block a to their initial positions.
• pile a onto b
where a and b are block numbers, moves the pile of blocks consisting of block a, and any blocks
that are stacked above block a, onto block b. All blocks on top of block b are moved to their
initial positions prior to the pile taking place. The blocks stacked above block a retain their order
when moved.
• pile a over b
where a and b are block numbers, puts the pile of blocks consisting of block a, and any blocks
that are stacked above block a, onto the top of the stack containing block b. The blocks stacked
above block a retain their original order when moved.
• quit
terminates manipulations in the block world.
Any command in which a = b or in which a and b are in the same stack of blocks is an illegal
command. All illegal commands should be ignored and should have no affect on the configuration of
blocks.
Input
The input begins with an integer n on a line by itself representing the number of blocks in the block
world. You may assume that 0 < n < 25.
The number of blocks is followed by a sequence of block commands, one command per line. Your
program should process all commands until the quit command is encountered.
You may assume that all commands will be of the form specified above. There will be no syntactically
incorrect commands.
Output
The output should consist of the final state of the blocks world. Each original block position numbered
i (0 ≤ i < n where n is the number of blocks) should appear followed immediately by a colon. If there
is at least a block on it, the colon must be followed by one space, followed by a list of blocks that appear
stacked in that position with each block number separated from other block numbers by a space. Don’t
put any trailing spaces on a line.
There should be one line of output for each block position (i.e., n lines of output where n is the
integer on the first line of input).
Sample Input
10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit
Sample Output
0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:

AC代码:
参考刘汝佳《算法竞赛入门经典》(第2版)

#include
#include
#include

using namespace std;
const int maxn=30;
vector<int>pile[maxn];
int n;

void find_loc(int a,int &pa,int &ha){
    for(pa=0;pafor(ha=0;haif(pile[pa][ha]==a) return;
}

void clear_above(int pa,int ha){
    for(int i=ha+1;iint tmp=pile[pa][i];
        pile[tmp].push_back(tmp);
    }
    pile[pa].resize(ha+1);
}

void pile_onto(int ha,int pa,int pb){
    for(int i=ha;ivoid print(){
    for(int i=0;icout<":";
        for(int j=0;jcout<<" "<cout<int main()
{
    cin>>n;
    int a,b,ha,hb,pa,pb;
    string s1,s2;
    for(int i=0;iwhile(cin>>s1 && s1!="quit"){
        cin>>a>>s2>>b;
        find_loc(a,pa,ha);
        find_loc(b,pb,hb);
        if(pa==pb) continue;
        if(s1=="move") clear_above(pa,ha);
        if(s2=="onto") clear_above(pb,hb);
        pile_onto(ha,pa,pb);
    }
    print();
    return 0;
}

例题5-3 Andy’s First Dictionary UVA - 10815

Andy, 8, has a dream - he wants to produce his
very own dictionary. This is not an easy task for
him, as the number of words that he knows is,
well, not quite enough. Instead of thinking up all
the words himself, he has a briliant idea. From
his bookshelf he would pick one of his favourite
story books, from which he would copy out all
the distinct words. By arranging the words in
alphabetical order, he is done! Of course, it is
a really time-consuming job, and this is where a
computer program is helpful.
You are asked to write a program that lists
all the different words in the input text. In this
problem, a word is defined as a consecutive se￾quence of alphabets, in upper and/or lower case.
Words with only one letter are also to be considered. Furthermore, your program must be CaSe In￾SeNsItIvE. For example, words like “Apple”, “apple” or “APPLE” must be considered the same.
Input
The input file is a text with no more than 5000 lines. An input line has at most 200 characters. Input
is terminated by EOF.
Output
Your output should give a list of different words that appears in the input text, one in a line. The
words should all be in lower case, sorted in alphabetical order. You can be sure that he number of
distinct words in the text does not exceed 5000.
Sample Input
Adventures in Disneyland
Two blondes were going to Disneyland when they came to a fork in the
road. The sign read: “Disneyland Left.”
So they went home.
Sample Output
a
adventures
blondes
came
disneyland
fork
going
home
in
left
read
road
sign
so
the
they
to
two
went
were
when

AC代码:
参考刘汝佳《算法竞赛入门经典》(第2版)

#include
#include
#include
#include
using namespace std;

int main()
{
    set<string>word;
    string s,buf;
    while(cin>>s){
        for(int i=0;iif(isalpha(s[i])) s[i]=tolower(s[i]); else s[i]=' ';
        stringstream ss(s);
        while(ss>>buf) word.insert(buf);
    }
    for(set<string>::iterator it=word.begin();it!=word.end();it++)
        cout<<*it<return 0;
}

例题5-4 Ananagrams UVA - 156

Most crossword puzzle fans are used to anagrams — groups of words with the same letters in different
orders — for example OPTS, SPOT, STOP, POTS and POST. Some words however do not have this
attribute, no matter how you rearrange their letters, you cannot form another word. Such words are
called ananagrams, an example is QUIZ.
Obviously such definitions depend on the domain within which we are working; you might think
that ATHENE is an ananagram, whereas any chemist would quickly produce ETHANE. One possible
domain would be the entire English language, but this could lead to some problems. One could restrict
the domain to, say, Music, in which case SCALE becomes a relative ananagram (LACES is not in the
same domain) but NOTE is not since it can produce TONE.
Write a program that will read in the dictionary of a restricted domain and determine the relative
ananagrams. Note that single letter words are, ipso facto, relative ananagrams since they cannot be
“rearranged” at all. The dictionary will contain no more than 1000 words.
Input
Input will consist of a series of lines. No line will be more than 80 characters long, but may contain any
number of words. Words consist of up to 20 upper and/or lower case letters, and will not be broken
across lines. Spaces may appear freely around words, and at least one space separates multiple words
on the same line. Note that words that contain the same letters but of differing case are considered to
be anagrams of each other, thus ‘tIeD’ and ‘EdiT’ are anagrams. The file will be terminated by a line
consisting of a single ‘#’.
Output
Output will consist of a series of lines. Each line will consist of a single word that is a relative ananagram
in the input dictionary. Words must be output in lexicographic (case-sensitive) order. There will always
be at least one relative ananagram.
Sample Input
ladder came tape soon leader acme RIDE lone Dreis peat
ScAlE orb eye Rides dealer NotE derail LaCeS drIed
noel dire Disk mace Rob dries
#
Sample Output
Disk
NotE
derail
drIed
eye
ladder
soon
AC代码(一):

//本题使用集合set来做的思路,先用字符串数组存放所有的输入,
//并且把“相同”的字符串标记为1,之后把所有非1的字符串插入集合中,再输出即可。

#include
#include
#include
#include
using namespace std;
//判断两个字符串是否“相同”
bool is_equal(string s1,string s2){
    int a[30]={0},b[30]={0};
    for(int i=0;itolower(s1[i]);
        a[s1[i]-'a']++;
    }
    for(int i=0;itolower(s2[i]);
        b[s2[i]-'a']++;
    }
    int flag=0;
    for(int i=0;i<26;i++){
        if(a[i]!=b[i]){
            flag=1;return 0;
        }
    }
    return 1;
}

int main()
{
    vector<string>vec;
    bool mark[1000]={0};
    string s1;
    //把所有字符串都插入到数组中,并把出现“相同”的字符串都标记成1,其余字符串标记为0
    while(cin>>s1){
        if(s1[0]=='#') break;
        vec.push_back(s1);
        for(int i=0;i1;i++){
            bool flag=is_equal(vec[i],s1);
            if(flag) mark[i]=mark[vec.size()-1]=1;
        }
    }

    //把所有满足要求的字符串写进set中,利用set本身已经排好序的特性,插入后直接输出即可
    set<string>set1;
    for(int i=0;iif(mark[i]!=1)
            set1.insert(vec[i]);
    }
    for(set<string>::iterator it=set1.begin();it!=set1.end();it++){
        cout<<*it<return 0;
}

AC代码(二):
参考刘汝佳《算法竞赛入门经典》(第2版)

#include
#include
#include
#include
#include
using namespace std;

map<string,int>cnt;
vector<string>word;

string stan(string s){
    for(int i=0;itolower(s[i]);
    }
    sort(s.begin(),s.end());
    return s;
}

int main()
{
    string s;
    while(cin>>s){
        if(s[0]=='#') break;
        word.push_back(s);
        string tmp=stan(s);
        if(!cnt.count(tmp)) cnt[tmp]=0;
        cnt[tmp]++;
    }
    vector<string>ans;
    for(int i=0;iif(cnt[stan(word[i])]==1) ans.push_back(word[i]);
    }
    sort(ans.begin(),ans.end());
    for(int i=0;icout<return 0;
}

例题5-5 The SetStack Computer UVA - 12096

Background from Wikipedia: “Set theory is a
branch of mathematics created principally by the
German mathematician Georg Cantor at the end of
the 19th century. Initially controversial, set theory
has come to play the role of a foundational theory
in modern mathematics, in the sense of a theory
invoked to justify assumptions made in mathematics
concerning the existence of mathematical objects
(such as numbers or functions) and their properties.
Formal versions of set theory also have a foundational
role to play as specifying a theoretical ideal
of mathematical rigor in proofs.”
Given this importance of sets, being the basis of mathematics, a set of eccentric theorist set off to
construct a supercomputer operating on sets instead of numbers. The initial SetStack Alpha is under
construction, and they need you to simulate it in order to verify the operation of the prototype.
The computer operates on a single stack of sets, which is initially empty. After each operation, the
cardinality of the topmost set on the stack is output. The cardinality of a set S is denoted |S| and is the
number of elements in S. The instruction set of the SetStack Alpha is PUSH, DUP, UNION, INTERSECT,
and ADD.
• PUSH will push the empty set {} on the stack.
• DUP will duplicate the topmost set (pop the stack, and then push that set on the stack twice).
• UNION will pop the stack twice and then push the union of the two sets on the stack.
• INTERSECT will pop the stack twice and then push the intersection of the two sets on the stack.
• ADD will pop the stack twice, add the first set to the second one, and then push the resulting set
on the stack.
For illustration purposes, assume that the topmost element of the stack is
A = {{}, {{}}}
and that the next one is
B = {{}, {{{}}}}
For these sets, we have |A| = 2 and |B| = 2. Then:
• UNION would result in the set {{}, {{}}, {{{}}}}. The output is 3.
• INTERSECT would result in the set {{}}. The output is 1.
• ADD would result in the set {{}, {{{}}}, {{},{{}}}}. The output is 3.
Input
An integer 0 ≤ T ≤ 5 on the first line gives the cardinality of the set of test cases. The first line of each
test case contains the number of operations 0 ≤ N ≤ 2000. Then follow N lines each containing one of
the five commands. It is guaranteed that the SetStack computer can execute all the commands in the
sequence without ever popping an empty stack.
Output
For each operation specified in the input, there will be one line of output consisting of a single integer.
This integer is the cardinality of the topmost element of the stack after the corresponding command
has executed. After each test case there will be a line with ‘*’ (three asterisks).
Sample Input
2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT
Sample Output
0
0
1
0
1
1
2
2
2


0
0
1
0
0


【思路】
下面的算法用了标记的方法,对每个集合进行编号标记,存在数组里面,每个集合会因其含有的编号而表示包含其他集合,这就完成了集合的集合的表示。
新知识:set_union,set_intersection求集合并集,交集

AC代码:
参考刘汝佳《算法竞赛入门经典》(第2版)

#include
#include
#include
#include
#include
#include
using namespace std;

vector<set<int> >set_vec;
map<set<int>,int>set_cnt;

int get_set_cnt(set<int> s){
    if(set_cnt.count(s)) return set_cnt[s];
    set_vec.push_back(s);
    return set_cnt[s]=set_vec.size()-1;
}

int main()
{
    int T;
    cin>>T;
    set<int>set0;//空集
    while(T--){
        set_vec.clear();
        set_cnt.clear();
        int n;
        cin>>n;
        stack<int>sta;
        while(n--){
            string str;
            cin>>str;
            if(str=="PUSH") sta.push(get_set_cnt(set0));
            else if(str=="DUP") sta.push(sta.top());
            else{
                set<int>set1=set_vec[sta.top()];sta.pop();
                set<int>set2=set_vec[sta.top()];sta.pop();
                set<int>set3;
                if(str=="UNION") set_union(set1.begin(),set1.end(),set2.begin(),set2.end(),inserter(set3,set3.begin()));
                if(str=="INTERSECT") set_intersection(set1.begin(),set1.end(),set2.begin(),set2.end(),inserter(set3,set3.begin()));
                if(str=="ADD") {set3=set2;set3.insert(get_set_cnt(set1));}
                sta.push(get_set_cnt(set3));
            }
            cout<cout<<"***"<return 0;
}

例题5-6 Team Queue UVA - 540

Queues and Priority Queues are data structures which are known to most computer scientists. The
Team Queue, however, is not so well known, though it occurs often in everyday life. At lunch time the
queue in front of the Mensa is a team queue, for example.
In a team queue each element belongs to a team. If an element enters the queue, it first searches
the queue from head to tail to check if some of its teammates (elements of the same team) are already
in the queue. If yes, it enters the queue right behind them. If not, it enters the queue at the tail
and becomes the new last element (bad luck). Dequeuing is done like in normal queues: elements are
processed from head to tail in the order they appear in the team queue.
Your task is to write a program that simulates such a team queue.
Input
The input file will contain one or more test cases. Each test case begins with the number of teams
t (1 ≤ t ≤ 1000). Then t team descriptions follow, each one consisting of the number of elements
belonging to the team and the elements themselves. Elements are integers in the range 0..999999. A
team may consist of up to 1000 elements.
Finally, a list of commands follows. There are three different kinds of commands:
• ENQUEUE x — enter element x into the team queue
• DEQUEUE — process the first element and remove it from the queue
• STOP — end of test case
The input will be terminated by a value of 0 for t.
Warning: A test case may contain up to 200000 (two hundred thousand) commands, so the imple￾mentation of the team queue should be efficient: both enqueing and dequeuing of an element should
only take constant time.
Output
For each test case, first print a line saying ‘Scenario #k’, where k is the number of the test case. Then,
for each ‘DEQUEUE’ command, print the element which is dequeued on a single line. Print a blank line
after each test case, even after the last one.
Sample Input
2
3 101 102 103
3 201 202 203
ENQUEUE 101
ENQUEUE 201
ENQUEUE 102
ENQUEUE 202
ENQUEUE 103
ENQUEUE 203
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
2
5 259001 259002 259003 259004 259005
6 260001 260002 260003 260004 260005 260006
ENQUEUE 259001
ENQUEUE 260001
ENQUEUE 259002
ENQUEUE 259003
ENQUEUE 259004
ENQUEUE 259005
DEQUEUE
DEQUEUE
ENQUEUE 260002
ENQUEUE 260003
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
0
Sample Output
Scenario #1
101
102
103
201
202
203

Scenario #2
259001
259002
259003
259004
259005
260001
【启发】
刘汝佳老师的算法非常巧妙哉!如下欣赏之!
AC代码:
参考刘汝佳《算法竞赛入门经典》(第2版)

#include
#include
#include
#include
using namespace std;

const int maxn=1005;

int main()
{
    int t,kase=0;
    while(cin>>t && t){

        map<int ,int>team;
        for(int i=1;i<=t;i++){
            int n,data;
            cin>>n;
            for(int j=1;j<=n;j++){
                cin>>data;
                team[data]=i;
            }
        }
        cout<<"Scenario #"<<++kase<queue<int>q,qq[maxn];
        string s;
        int num;
        while(cin>>s){
            if(s=="ENQUEUE"){
                cin>>num;
                int x=team[num];
                if(qq[x].empty()) q.push(x);
                qq[x].push(num);
            }
            if(s=="DEQUEUE"){
                int x=q.front();
                int e=qq[x].front();
                qq[x].pop();
                cout<if(qq[x].empty()) q.pop();  //该句很关键
            }
            if(s=="STOP"){
                cout<break;
            }
        }
    }
    return 0;
}

例题5-7 Ugly Numbers UVA - 136

Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
shows the first 11 ugly numbers. By convention, 1 is included.
Write a program to find and print the 1500’th ugly number.
Input
There is no input to this program.
Output
Output should consist of a single line as shown below, with ‘’ replaced by the number
computed.
Sample Output
The 1500’th ugly number is .

【本题目有错误】
题目中最后的输出要求是The 1500’th ugly number is .事实上,不要用尖括号括住number,否则错误。

AC代码:
参考刘汝佳《算法竞赛入门经典》(第2版)

#include
#include
#include
#include
using namespace std;

typedef long long ll;

int main()
{
    sets;
    priority_queuevector,greater >pq;
    int a[6]={2,3,5};
    s.insert(1);
    pq.push(1);
    for(int i=1;;i++){
        ll e=pq.top();pq.pop();
        if(i==1500){
            cout<<"The 1500'th ugly number is "<"."<break;
        }
        for(int j=0;j<3;j++){
            ll x=e*a[j];
            if(!s.count(x)){s.insert(x);pq.push(x);}
        }
    }
    return 0;
}

你可能感兴趣的:(紫书算法学习记)