文章目录

  • 试题链接
  • 学习笔记 - C++ STL
    • 简介
    • STL容器实验
      • 序列式容器
      • 关联式容器
      • 集合容器
  • A - The Blocks Problem (POJ 1208, UVA 101)
    • 中文释义
    • 解题分析
    • 解题代码
  • B - Broken Keyboard (a.k.a. Beiju Text) (UVA 11988)
    • 中文释义
    • 解题分析
    • 解题代码
  • C - Babelfish (POJ 2503)
    • 中文释义
    • 解题分析
    • 解题代码
  • D - Ananagrams (UVA 156)
    • 中文释义
    • 解题分析
    • 解题代码
  • E - Concatenation of Languages (UVA 10887)
    • 中文释义
    • 解题分析
    • 解题代码
  • F - The Spot Game (UVA 141)
    • 中文释义
    • 解题分析
    • 解题代码
  • G - Conformity (POJ 3640, UVA 11286)
    • 中文释义
    • 解题分析
    • 解题代码

试题链接

点我进入代码提交OJ

学习笔记 - C++ STL

简介

• STL(Standard Template Library),也被称为标准模板库,包含大量的模板类和模板函数,是C++提供的一个由一些容器、算法和其他一些组件组成的集合。用于完成诸如输入/输出、数学计算等功能。
• STL被内置到支持C++的编译器中。在C++标准中,STL被组织为13个头文件:<iterator>,<functional>,<vector>,<deque>,<list>,<queue>,<stack>,<set>,<map>,<algorithm>,<numeric>,<memory>,和<utility>。
• STL是由容器、算法、迭代器、函数对象、适配器、内存分配器这6部分构成;其中,后面的4个部分是为前面的2个部分服务的;容器是一些封装数据结构的模板类,例如vector 向量容器、list列表容器等;STL 提供了非常多(大约100 个)的数据结构算法,这些算法被设计为模板函数,在std命名空间中定义,其中大部分算法都包含在头文件<algorithm>中,少部分位于头文件<numeric>中。

STL容器实验

STL有两类共七种基本容器类型。
• 序列式容器,此为可序群集,其中每个元素的位置取决于插入的顺序,和元素值无关。STL提供三个序列式容器:向量(vector)、双端队列(deque)、列表(list),此外,string和array也可以被视为序列式容器。
• 关联式容器,此为已序群集,其中每个元素位置取决于特定的排序准则以及元素值,和插入次序无关。STL提供了四个关联式容器:集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)。

序列式容器

• vector容器被称为向量容器,是一种序列式容器。vector容器和数组非常类似,但比数组优越,vector实现的是一个动态数组,在进行元素的插入和删除的过程中,vector会动态调整所占用的内存空间。在中间插入和删除慢,但在末端插入和删除快。
• 在创建vector容器之前,程序中要包含如下内容:

#include <vector>
using namespace std;

• 创建vector容器的方式有很多,基本形式为vector ,其中T表示存储元素的类型;例如,vector<double> values; 创建存储double类型元素的一个vector容器values。vector容器包含了很多的成员函数。

• 容器deque和容器vector都是序列式容器,都是采用动态数组来管理元素,能够快速地随机访问任一个元素,并且能够在容器的尾部快速地插入和删除元素。不同之处在于,deque还可以在容器首部快速地插入、删除元素。因此,容器deque也被称为双端队列。

• 使用deque容器之前要加上<deque>头文件:#include<deuqe>。

关联式容器

• map是STL的一个关联容器, 一个map是一个键值(key, value)对的序列,key和value可以是任意的类型。在一个map中key值是唯一的。map提供一对一的数据处理能力,在编程需要处理一对一数据的时候,可以采用map进行处理。
• 使用map容器,首先,程序要有包含map类所在的头文件:#include <map>;map对象是模板类,定义map需要key和value两个模板参数,例如,std:map<int, string> personnel;就定义了一个用int作为key(索引),相关联的指针指向类型为string的value,map容器名为personnel。

集合容器

• 集合(set),就是具有共同性质的一些对象汇集成一个整体。set容器用于存储同一数据类型的元素,并且能从中取出数据。在set中每个元素的值唯一,而且系统能根据元素的值自动进行排序。

• 使用set容器,首先,程序要有包含set类所在的头文件:#include <set>。定义set集合对象需要指出集合中元素的类型,例如,set<int>s;元素以int作为类型,set容器名为s。在【E - Concatenation of Languages】的参考程序中,set中的元素为字符串。

A - The Blocks Problem (POJ 1208, 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:

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:

中文释义

输入整数n,表示有编号为0~n-1的木块,分别放在顺序排列编号为0~n-1的位置。
设a和b是木块块号。现对这些木块进行操作,操作指令有如下四种:

• move a onto b:把a、b上的木块放回各自原来的位置,再把a放到b上;
• move a over b:把a上的木块放回各自的原来的位置,再把a放到包含了b的堆上;
• pile a onto b:把b上的木块放回各自的原来的位置,再把a以及在a上面的木块放到b上;
• pile a over b:把a连同a上木块放到包含了b的堆上。

当输入quit时,结束操作并输出0~n-1位置上的木块情况。
在操作指令中,如果a = b,其中a和b在同一堆块,则该操作指令是非法指令。非法指令要忽略,并且不应影响块的放置。

• 输入
输入的第一行给出一个整数n,表示木块的数目。本题设定0 < n < 25。
然后给出一系列操作指令,每行一个操作指令。您的程序要处理所有命令直到遇到quit指令。
本题设定,所有的操作指令都是上面给出的格式,不会有语法错误的指令。

• 输出
输出给出木块的最终状态。每个原始块位置i(0<=i<n,其中n是木块的数目)之后给出一个冒号。如果在这一位置至少有一个木块,则冒号后面输出一个空格,然后输出在该位置的一个木块列表,每个木块编号与其他块编号之间用空格隔开。在一行结束时不要在结尾加空格。
每个块位置要有一行输出(也就是说,要有n行输出,其中n是第一行输入给出的整数)。

解题分析

• 本题用vector容器vector <int> v[24]来表示木块,相当于一个二维数组,列确定,每列的行(木块数)不确定;并基于操作指令的规则,用vector容器的成员函数模拟对这些木块进行的操作。

• 首先,设计两个函数:find_pile_height(int a, int &p, int &h),返回木块a所在的堆号p以及a的高度h;clear_above(int p, int h),把第p堆第h个木块以上的木块放置到原来位置。然后,在这两个函数,以及vector容器的成员函数size()和push_back()的基础上,根据操作指令的规则,每种操作指令都用一个函数实现。最后,在主程序中逐条实现操作指令。

解题代码

#include<vector>
#include<string>
#include<iostream>
using namespace std;
int n;
vector<int> v[24];                            //相当于一个二维数组,列确定,每列的行(木块数)不确定void find_pile_height(int a,int& p,int& h)    //找到木块a所在的堆号p以及a的高度h
{for(p=0;p<n;p++)for(h=0;h<v[p].size();h++)         //vector容器的成员函数size(),返回元素个数if(v[p][h]==a)return;
}void clear_above(int p,int h)              //把第p堆第h个木块以上的木块放置到原来位置
{for(int i=h+1;i<v[p].size();i++){int b=v[p][i];v[b].push_back(b);                  //vector容器的成员函数push_back(),在序列尾部添加元素}v[p].resize(h+1);                      //vector容器的成员函数resize(),只保留0~h个元素
}void moveOnto(int a,int b)                 //move a onto b:把a、b上的木块放回各自原来的位置,再把a放到b上
{int pa,ha,pb,hb;find_pile_height(a,pa,ha);             //找到木块a和b所在的堆号以及高度hfind_pile_height(b,pb,hb);if(pa!=pb)                                //a和b不在同一堆,则操作{clear_above(pa,ha);                   //a和b所在的堆中clear_above(pb,hb);v[pb].push_back(a);v[pa].resize(ha);}
}void moveOver(int a,int b)                 //move a over b:把a上的木块放回各自的原来的位置,再把a放到包含了b的堆上
{int pa,ha,pb,hb;find_pile_height(a,pa,ha);find_pile_height(b,pb,hb);if(pa!=pb){clear_above(pa,ha);v[pb].push_back(a);v[pa].resize(ha);}
}void pileOnto(int a,int b)                 //pile a onto b:把b上的木块放回各自的原来的位置,再把a以及在a上面的木块放到b上
{int pa,ha,pb,hb;find_pile_height(a,pa,ha);find_pile_height(b,pb,hb);if(pa!=pb){clear_above(pb,hb);for(int i=ha;i<v[pa].size();i++)v[pb].push_back(v[pa][i]);v[pa].resize(ha);}
}void pileOver(int a,int b)                 //pile a over b:把a连同a上的木块放到包含了b的堆上
{int pa,ha,pb,hb;find_pile_height(a,pa,ha);find_pile_height(b,pb,hb);if(pa!=pb){for(int i=ha;i<v[pa].size();i++)v[pb].push_back(v[pa][i]);v[pa].resize(ha);}
}int main()
{int i,j;cin >> n;                                //n:木块的数目for(i=0;i<n;i++)                      //初始化,0~n-1的木块放到0~n-1的位置v[i].push_back(i);                   //push_back():在序列v[i]尾部添加木块iint a,b;                             //木块a和b的块号string str1,str2;                     //操作指令中的字符串cin >> str1;while(str1 != "quit")                   //每次循环处理一条操作指令{cin >> a >> str2 >> b;if(str1=="move" && str2=="onto")moveOnto(a,b);if(str1=="move" && str2=="over")moveOver(a,b);if(str1=="pile" && str2=="onto")pileOnto(a,b);if(str1=="pile" && str2=="over")pileOver(a,b);cin >> str1;}for(i=0;i<n;i++)                        //输出木块的最终状态{cout << i << ":";for(j=0;j<v[i].size();j++)cout << " " << v[i][j];cout << endl;}return 0;
}

B - Broken Keyboard (a.k.a. Beiju Text) (UVA 11988)

中文释义

• 您正在用一个坏键盘键入一个长文本。这个键盘的问题是时不时“Home”键或“End”键会在您输入文本时自动按下。您并没有意识到这个问题,因为你只关注文本,甚至没有打开显示器。完成键入后,您打开显示器,在屏幕上看到文本。在中文里,我们称之为悲剧。请您是找到悲剧的文本。

• 输入
输入给出若干测试用例。每个测试用例都是一行,包含至少一个,最多100,000个字母、下划线和两个特殊字符‘[’和‘]’;其中‘[’表示“Home”键,而‘]’表示“End”键。输入以EOF结束。

• 输出
对于每个测试用例,输出在屏幕上的悲剧的文本。

解题分析

• 本题题意:对于每个输入的字符串,如果出现’ [ ‘,则输入光标就跳到字符串的最前面,如果出现’ ] ',则输入光标就跳到字符串的最后面。输出实际上显示在屏幕上的字符串。

• 本题可以用双端队列模拟试题描述给出的规则,用字符串变量s存储输入的字符串,deque容器deque <string> dq来产生在屏幕上的悲剧的文本。在输入字符串s后,对s中的字符逐个处理:当前字符如果不是’ [ ‘或’ ] ‘,则当前字符加入到中间字符串temp中(temp+=s[i]);当前字符如果是’ [ ‘,则中间字符串temp的内容插入到deque容器dq的首部;当前字符如果是’ ] ',则中间字符串temp的内容插入到deque容器dq的尾部。

• 最后,从deque容器dq中逐个输出字符。

• 本题的参考程序用到字符串操作函数clear(),删除全部字符;size(),返回字符数量;以及c_str(),将内容以C_string返回。

解题代码

#include<deque>
#include<string>
#include<iostream>
using namespace std;
string s,temp;
deque<string> dp;                         //创建一个空的deque容器dp
int main()
{while(cin >> s)                          //每个测试用例一行字符串s{char op=0;int i;temp.clear();                       //清空字符串tempfor(i=0;i<s.size();i++)                //对s中的字符逐个处理{if(s[i]=='[' || s[i]==']')     //deque容器dp实现规则{if(op=='[')dp.push_front(temp); //deque容器的成员函数push_front(),将中间字符串temp的内容插入到deque容器dq的首部elsedp.push_back(temp);       //deque容器的成员函数push_back(),将中间字符串temp的内容插入到deque容器dq的尾部temp.clear();op=s[i];}elsetemp+=s[i];if(i==s.size()-1)                //处理在中间字符串temp的最后一段字符串{if(op=='[')dp.push_front(temp);elsedp.push_back(temp);temp.clear();}}while(!dp.empty())                  //从deque容器dq中逐个输出字符{printf("%s",dp.front().c_str());//deque容器的成员函数front(),容器的第一个元素的引用:c_str():将内容以C_string返回dp.pop_front();                  //deque容器的成员函数pop_front(),删除首部数据}puts("");}return 0;
}

C - Babelfish (POJ 2503)

You have just moved from Waterloo to a big city. The people here speak an incomprehensible dialect of a foreign language. Fortunately, you have a dictionary to help you understand them.

Input
Input consists of up to 100,000 dictionary entries, followed by a blank line, followed by a message of up to 100,000 words. Each dictionary entry is a line containing an English word, followed by a space and a foreign language word. No foreign word appears more than once in the dictionary. The message is a sequence of words in the foreign language, one word on each line. Each word in the input is a sequence of at most 10 lowercase letters.

Output
Output is the message translated to English, one word per line. Foreign words not in the dictionary should be translated as “eh”.

Sample Input
dog ogday
cat atcay
pig igpay
froot ootfray
loops oopslay

atcay
ittenkay
oopslay

Sample Output
cat
eh
loops

Hint
Huge input and output,scanf and printf are recommended.

中文释义

• 您离开Waterloo到另外一个大城市。那里的人们说着一种让人费解的外语。不过幸运的是,您有一本词典可以帮助你来理解这种外语。

• 输入
首先输入一个词典,词典中包含不超过100000个词条,每个词条占据一行。每一个词条包括一个英文单词和一个外语单词,在两个单词之间用一个空格隔开。而且在词典中不会有某个外语单词出现超过两次。词典之后是一个空行,然后给出不超过100000个外语单词,每个单词一行。输入中出现单词只包括小写字母,而且长度不会超过10。

• 输出
在输出中,请您把输入的单词翻译成英文单词,每行输出一个英文单词。如果某个外语单词不在词典中,就把这个单词翻译成“eh”。

解题分析

• 本题需要处理一对一(英文单词、外语单词)数据,所以使用map容器mp,key和value的类型是string。首先,输入词典,以外语单词为key,英文单词为value,在map中插入词条(mp[Foreign]=English);然后,输入要查询的外语单词,从map容器mp中,获取英文单词(mp[Foreign])。

解题代码

#include<map>                              //包含map类所在的头文件
#include<string>
#include<iostream>
using namespace std;
int main()
{char english[10],foreign[10];          //english:英文单词,foreign:外语单词char str[25];                           //输入的字符串map<string,string>mp;                 //定义map容器mpwhile(gets(str) && str[0]!='\0')      //输入词典:每次循环一个词条;空行:词典结束{sscanf(str,"%s %s",english,foreign);//sscanf:以固定字符串为输入源mp[foreign]=english;              //在map中插入元素,用数组方式插入值}while(gets(str) && str[0]!='\0')     //每次循环处理一个要查询的外语单词{sscanf(str,"%s",foreign);if(mp[foreign] != "\0")                //获取map中的元素cout << mp[foreign] << endl;elsecout << "eh" << endl;}return 0;
}

D - Ananagrams (UVA 156)

中文释义

• 大多数填字游戏迷熟悉变形词(anagrams)——一组有着相同的字母但字母位置不同的单词,例如OPTS, SPOT, STOP, POTS和POST。有些单词没有这样的特性,无论您怎样重新排列其字母,都不可能构造另一个单词。这样的单词被称为非变形词(ananagrams),例如QUIZ。

• 当然,这样的定义是要基于您所工作的领域的。例如,您可能认为ATHENE是一个非变形词,而一个化学家则会很快地给出ETHANE。一个可能的领域是全部的英语单词,但这会导致一些问题。如果将领域限制在Music中,在这一情况下,SCALE是一个相对的非变形词(LACES不在这一领域中),但可以由NOTE产生TONE,所以NOTE不是非变形词。

• 请您编写一个程序,输入某个限制领域的词典,并确定相对非变形词。注意单字母单词实际上也是相对非变形词,因为它们根本不可能被“重新安排”。字典包含不超过1000个单词。

• 输入
输入由若干行组成,每行不超过80个字符,且每行包含单词的个数是任意的。单词由不超过20个的大写和/或小写字母组成,没有下划线。空格出现在单词之间,在同一行中的单词至少用一个空格分开。含有相同的字母,而大小写不一致的单词被认为彼此是变形词,如tIeD和EdiT是变形词。以一行包含单一的#作为输入终止。

• 输出
输出由若干行组成,每行给出输入字典中的一个相对非变形词的单词。单词输出按字典序(区分大小写)排列。至少有一个相对非变形词。

解题分析

• 若当前单词的升序串与某单词的升序串相同,则说明该单词是相对变形词;若当前单词的升序串不同于所有其它单词的升序串,则该单词是非相对变形词。由此给出算法:

• 首先,通过函数getkey(string& s),输入的字符串s中的字母改为小写字母,并按字母升序排列;然后,在map容器dict中,用数组方式插入处理后的字符串,累计字符串的重复次数值;而输入的原始字符串添加到vector容器words中。接下来,对vector容器words中的每个字符串进行判断,如果是非相对变形词,则插入到vector容器ans中;最后,对vector容器ans中的所有相对非变形词按字典序进行排列,然后输出。

解题代码

#include<map>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
map<string,int> dict;
vector<string> words;
vector<string> ans;
string getkey(string& s)            //输入字符串改为小写字母,按字母升序排列
{string key=s;for(int i=0;i<key.length();i++)key[i]=tolower(key[i]);        //tolower():把给定的字母转换为小写字母sort(key.begin(),key.end());    //字符串按升序排列return key;
}
int main()
{string s;int i;while(cin >> s && s[0] != '#') //每次循环,处理一个输入的字符串{string key=getkey(s);dict[key]++;               //map容器dict中,累计key的重复次数words.push_back(s);           //push_back():在vector容器words的最后添加输入的字符串s}for(i=0;i<words.size();i++)       //vector容器words中的每个字符串if(dict[getkey(words[i])]==1)//非相对变形词ans.push_back(words[i]);sort(ans.begin(),ans.end());for(i=0;i<ans.size();i++)        //输出非相对变形词cout << ans[i] << "\n";return 0;
}

E - Concatenation of Languages (UVA 10887)

中文释义

一种语言是一个字符串组成的集合。两种语言的拼接是在第一种语言的字符串的结尾处拼接第二种语言的字符串而构成的所有字符串的集合。

例如,如果给出两种语言A和B:

• A = {cat, dog, mouse};
• B = {rat, bat};

则A和B的连接是:

• C = {catrat, catbat, dograt, dogbat, mouserat, mousebat}。

给出两种语言,请您计算两种语言拼接所产生的字符串的数目。

• 输入
输入有多个测试用例。输入的第一行给出测试用例的数目T(1≤T≤25)。接下来给出T个测试用例。每个测试用例的第一行给出两个整数,M和N(M, N < 1500),是每种语言中字符串的数量。然后,M行给出第一种语言的字符串;接下来的N行给出了第二种语言的字符串。本题设定字符串仅由小写字母(‘a’到’z’)组成,长度小于10个字符,并且每个字符串在一行中给出,没有任何前导或尾随的空格。

输入语言中的字符串可能不会被排序,并且不会有重复的字符串。

• 输出
对于每个测试用例,输出一行。每个测试用例的输出是以测试用例的序列号开始,然后给出在第一种语言的字符串之后拼接第二种语言中的字符串所产生的字符串数。

解题分析

• 本题采用set容器存储两种语言拼接之后所产生的字符串集合,“set<string>s1;”定义set集合对象s1;其中,方法insert()在集合中插入元素,将拼接产生的字符串插入集合;方法size()返回集合中元素的数目,以此给出在第一种语言的字符串之后拼接第二种语言中的字符串所产生的字符串数;而方法clear()清空集合中的所有元素。

• 对于每个测试用例,将第一种语言的字符串和第二种语言的字符串拼接,产生的字符串插入set容器s1中;然后,通过方法size()返回拼接所产生的字符串数。

解题代码

#include<set>
#include<cstring>
#include<iostream>
using namespace std;
char str1[1500][10];                //第一种语言的字符串
char str2[1500][10];                //第二种语言的字符串
int main()
{int cas=1;                        //测试用例序号set<string>s1;                    //两种语言的字符串拼接后所产生的字符串集合int t,i,j;scanf("%d",&t);                   //输入测试用例数while(t--)                     //每次循环处理一个测试用例{int n,m;                 //两种语言中的字符串数量scanf("%d%d",&n,&m);getchar();                   //读取多余的回车符for(i=0;i<n;i++)            //输入第一种语言的字符串gets(str1[i]);for(i=0;i<m;i++)           //输入第二种语言的字符串gets(str2[i]);for(i=0;i<n;i++)for(j=0;j<m;j++){char tmp[20];       //两个字符串连接所产生的字符串strcpy(tmp,str1[i]);strcat(tmp,str2[j]);s1.insert(tmp);     //拼接产生的字符串插入集合s1}printf("Case %d: %d\n",cas++,s1.size());   //集合s1中的元素数s1.clear();                  //清空集合s1}return 0;
}

F - The Spot Game (UVA 141)

中文释义

• Spot游戏在一个NN的棋盘上进行,如图所示的Spot游戏,N=4。在游戏的过程中,两个玩家交替,一次走一步:一个玩家一次可以在一个空方格中放置一枚黑色的棋子(点),也可以从棋盘上取走一枚棋子,从而产生各种各样的棋盘图案。如果一个棋盘图案(或其旋转90度或180度)在游戏中被重复,则产生该图案的玩家就失败,而另一个玩家获胜。如果在此之前没有重复的图案产生,在2N步后,游戏平局。

• 如果第一个图案是在早些时候产生的,那么产生后面三个图案中的任何一个(还有一个,第一个图案旋转180度,没有给出),都会终止游戏;而产生最后一个图案则不会结束游戏。

• 输入
输入给出一系列的游戏,每局游戏首先在一行中给出棋盘的大小N,(2N50);然后给出玩家的2N步,无论它们是否是必要的。每一步先给出一个正方形的坐标(1…N范围内的整数),然后给出一个空格,以及一个分别表示放置一枚棋子或拿走一枚棋子的字符“+”或“-”。本题设定玩家的每一步都是合法的,也就是说,不会在一个已经放置了棋子的方格里再放置一枚棋子,也不会从一个不存在棋子的方格里拿走棋子。输入将以零(0)为结束。

• 输出
对于每局游戏,输出一行,表明哪位选手赢了,以及走到哪一步,或者比赛以平局结束。

解题分析

• 在参考程序中,棋局表示为一个结构。每输入一个棋局,就将这一个棋局的四种旋转都存储在一个集合中。这样,对于棋局序列中的每个棋局,可以判断该棋局是否在集合中存在,如果已经存在,则根据步数判定赢家。走完2N步,没有重复棋局,则为平局。

• 由于set的具体实现采用了红黑树的平衡二叉树的数据结构,所以,set中的元素就有大小比较。在参考程序中,给出重载函数booloperator < (const spot& a, const spot& b),以比较两个结构的大小,便于在set中插入和查找元素。

解题代码

#include<set>
#include<cstring>
#include<iostream>
using namespace std;
const int nmax=51;
int n;
struct spot
{bool arr[nmax][nmax];
}p;
bool operator < (const spot& a,const spot& b)        //重载函数
{for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(a.arr[i][j] < b.arr[i][j])return true;else    if(a.arr[i][j] > b.arr[i][j])return false;return false;
}
void changs(spot& w)                                //将棋局逆时针旋转90°
{spot a;for(int i=0;i<=n;i++)for(int j=1;j<=n;j++)a.arr[i][j]=w.arr[j][n+1-i];w=a;
}
int main()
{int a,b;char c;while(scanf("%d",&n) && n){bool flag=false;                  //棋局重复标志set<spot>s;                           //把棋局(二维数组)的结构体作为集合元素memset(p.arr,false,sizeof(p.arr));int count=0;for(int num=1;num<=2*n;num++){scanf("%d%d %c",&a,&b,&c);       //输入每一步if(flag)continue;if(c=='+')                     //放置棋子p.arr[a][b]=true;else                            //取走棋子p.arr[a][b]=false;if(s.count(p))                 //当前棋局在集合中已经有了{flag=true;count=num;                   //走了几步continue;}spot t(p);for(int j=0;j<4;j++)            //将棋局旋转的四种情况插入到set里面{s.insert(t);changs(t);}}if(flag)                           //棋局重复,判定赢家if(count%2 == 0)printf("Player 1 wins on move %d\n",count);elseprintf("Player 2 wins on move %d\n",count);elseprintf("Draw\n");}return 0;
}

G - Conformity (POJ 3640, UVA 11286)

Frosh commencing their studies at Waterloo have diverse interests, as evidenced by their desire to take various combinations of courses from among those available.

University administrators are uncomfortable with this situation, and therefore wish to offer a conformity prize to frosh who choose one of the most popular combinations of courses. How many frosh will win the prize?

Input
The input consists of several test cases followed by a line containing 0. Each test case begins with an integer 1 ≤ n ≤ 10000, the number of frosh. For each frosh, a line follows containing the course numbers of five distinct courses selected by the frosh. Each course number is an integer between 100 and 499.

The popularity of a combination is the number of frosh selecting exactly the same combination of courses. A combination of courses is considered most popular if no other combination has higher popularity.

Output
For each line of input, you should output a single line giving the total number of students taking some combination of courses that is most popular.

Sample Input
3
100 101 102 103 488
100 200 300 101 102
103 102 101 488 100
3
200 202 204 206 208
123 234 345 456 321
100 200 300 400 444
0

Sample Output
2
3

中文释义

• 在Waterloo大学,一年级的新生们开始了学业,他们有着不同的兴趣,他们要从现有的课程中选择不同的课程组合,进行选修。

• 大学的领导层对这种情况感到不安,因此他们要为选修最受欢迎的课程组合之一的一年级新生颁奖。会有多少位一年级新生获奖呢?

• 输入
输入由若干个测试用例组成,在测试用例的最后给出包含0的一行。每个测试用例首先给出一个整数1≤n≤10000,表示一年级新生的数量。对于每一个一年级新生,后面都会给出一行,包含这位新生选修的五个不同课程的课程编号。每个课程编号是100到499之间的整数。

课程组合的受欢迎程度是选择完全相同的课程组合的一年级新生的数量。如果没有其他的课程组合比某个课程组合更受欢迎,那么这个课程组合被认为是最受欢迎的。

• 输出
对于每一个测试用例,输出一行,给出选修最受欢迎的课程组合的学生总数。

解题分析

• 有n位学生选课,每位学生选修5门课,有5个不同的课程号。要求找出选修最受欢迎的课程组合的学生数量;如果有多个课程组合是最受欢迎的,则计算选修这些组合的学生总数。

• 一个学生选课的5个不同的课程号,用STL的set(集合)容器suit来存储;而n位学生选课,则STL的map容器count来存储,map将相同集合(相同的课程组合)存储在同一位置,在存入一个集合时,该集合出现次数增加1。同时,记录出现最多的课程组合的次数M,以及出现次数为M的课程组合数MC。最后输出M*MC。

解题代码

#include<map>
#include<set>
#include<iostream>
using namespace std;
int main()
{int n;                     //n位学生选课while(cin >> n,n){map<set<int>,int> count;int m=0,mc=0,i;while(n--){set<int> suit;for(i=0;i<5;i++)  //一个学生选课的5个不同的课程号{int cour;cin >> cour;suit.insert(cour); //在集合suit中插入元素}count[suit]++;     //集合出现次数增加1int h=count[suit];if(h==m)mc++;if(h>m)m=h,mc=1;}cout << m*mc << endl;}return 0;
}

ICPC训练联盟2021寒假冬令营(6)_2021.01.25_笔记相关推荐

  1. ICPC训练联盟2021寒假冬令营(5)_2021.01.22_笔记

    文章目录 试题链接 学习笔记-高效排序算法( O(nlogn)时间复杂度 ) 算法介绍 归并排序 主要思路 算法图解 算法代码 快速排序 主要思路 算法代码 十大排序算法的动画演示链接 C++STL排 ...

  2. ICPC训练联盟2021寒假冬令营(7)_2021.01.26_笔记

    文章目录 试题链接 学习笔记 - C++STL.贪心算法 C++STL 迭代器 STL算法 关联式容器 贪心算法 介绍 使用贪心法能否得到最优解,是必须加以证明的. 体验贪心法内涵的实验范例 贪心法的 ...

  3. ICPC训练联盟2021寒假冬令营(4)_2021.01.21_笔记

    文章目录 试题链接 学习笔记-排序算法( O(n^2^)时间复杂度 ) 选择排序程序段(C++) 冒泡排序程序段(C++) 插入排序程序段 A - Necklace (UVA 11001) 中文释义 ...

  4. ICPC训练联盟2021寒假冬令营(9)_2021.01.29_笔记

    试题链接 点我进入代码提交OJ 学习笔记 - 数论与组合分析入门 数论的编程实验 • 3.1素数运算的实验范例 • 3.2求解不定方程和同余方程的实验范例 • 3.3 特殊的同余式 • 3.4 积性函 ...

  5. ICPC训练联盟2021寒假冬令营(5)(部分题解):

    ICPC训练联盟2021寒假冬令营(5)(部分题解): A - Brainman Raymond Babbitt drives his brother Charlie mad. Recently Ra ...

  6. ICPC训练联盟2021寒假冬令营(7)部分题解

    ICPC训练联盟2021寒假冬令营(7)部分题解: A - Doubles As part of an arithmetic competency program, your students wil ...

  7. ICPC训练联盟2021寒假冬令营(2)

    文章目录 ICPC训练联盟2021寒假冬令营(2) [A - Maya Calendar](https://vjudge.net/problem/POJ-1008) 题目 分析 代码 [B - Dip ...

  8. ICPC训练联盟2021寒假冬令营(2)(部分题解)

    ICPC训练联盟2021寒假冬令营(2)(部分题解) B - Diplomatic License In an effort to minimize the expenses for foreign ...

  9. 【算法笔记】【几何初步、数学初步、矩阵计算】ICPC训练联盟2021寒假冬令营(3)笔记

    题目链接 A题题解:枚举法+简单直线方程知识. 本题采取枚举方法,在[-500, 500]的范围内枚举A和B,将樱桃坐标代入直线方程Ax+By,如果Ax+By大于0,则樱桃在直线方:小于0,则樱桃在直 ...

最新文章

  1. DELL服务器装2003系统
  2. windows mysql增量备份_windows下mysql增量备份与全备份批处理
  3. wifi的基础知识及原理1
  4. ue4sky时间_UE4 SkyLight RealTimeCapture浅析
  5. SAP CRM和Cloud for Customer的数据同步一例
  6. 算法(27)-最大系列
  7. leetcode题解77-组合
  8. 拉格朗日(lagrange)插值及其MATLAB程序
  9. dedecms 封面模板和列表模板有什么不同
  10. 14、 Integer 与 int 的区别
  11. python comprehensions_Python中的Comprehensions和Generations
  12. html中的表格背景透明度标签,透明度 背景
  13. 基站位置查询系统_Android获取手机基站位置并进行基站定位的原理
  14. Python绘制双坐标图
  15. C语言编辑时光标一直闪,win7系统编辑文字鼠标光标一直闪烁问题的解决方法 - win7吧...
  16. vxe-table 如何用回车键替换 Tab 键功能,回车切换到右侧单元格,回车切换下一个单元格
  17. Git Bash 下进行快速复制粘贴
  18. 利用Python将选择题、多选题导入Anki
  19. Windows上获取网卡的mac地址
  20. 目前用到的原型设计工具总结

热门文章

  1. MacBook雷电3接口失灵不可用
  2. 8255实现数码显示管显示两位数字
  3. 淘宝卖家中心打开淘宝客推广网页空白
  4. 微信的API到底是什么?
  5. Springboot启动后频繁打印错误日志 /null/swagger-ui.html解决方案
  6. C++实现复杂链表的复制
  7. Node.js基础入门
  8. 消防设施操作员考试真题、模拟练习题库(7)
  9. win10去除右下角激活水印
  10. Python度分秒与度的互转