ICPC訓練聯盟2021寒假冬令營(6)部分題解:
技術標籤:c++
**
ICPC訓練聯盟2021寒假冬令營(6)部分題解
**
寫好忘發了~~
A - The Blocks Problem
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.
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的區域(初始時區域i上方僅有木塊i),給定一系列指令,輸出操作後所有區域的木塊情況,其中指令有:
1.move a onto b: 把a、b上的木塊全放回原位置,再將a放到b上;
2.move a over b: 把a上的木塊全放回原位置,再將a放到包含了b的木塊堆上方;
3.pile a onto b : 把b上方的木塊全放回原位置,再將a以上(包含a)的所有木塊移到b上;
4.pile a over b : 把a以上(包含a)的所有木塊移到含有b的木塊堆上
5.quit : 操作結束
利用vector,模擬操作過程即可
程式碼:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
#define N 50005
#define PI acos(-1.0)
#define reset(x) memset(x,0,sizeof(x))
typedef long long int ll;
vector<int> org[30]; //n個位置,第一維是位置i,第二維存放木塊
int rec[30]; //記錄i目前位置
vector<int>::iterator restore(int n){ //將n及其上方木塊放回原位
int x=rec[n];
vector<int>::iterator t;
for(t=org[x].begin();t!=org[x].end();t++) //找到待刪除的元素
if(*t==n) break;
t++; //從i的上方第一塊開始放回原位
for(;t!=org[x].end();)
{
rec[*t]=*t; //位置還原
org[*t].push_back(*t);
org[x].erase(t);
}
return t-1; //返回n的位置,方便移動操作
}
int piles_move(int a,int b){ //把包含a和a以上的木塊全放到包含b的堆上
if(rec[a]==rec[b]) return 0; //a,b本來就在同一個位置,不必移動
vector<int>::iterator t;
int x=rec[a];
for(t=org[x].begin();t!=org[x].end();t++)
if(*t==a) break;
for(;t!=org[x].end();){
org[rec[b]].push_back(*t);
rec[*t]=rec[b]; //更新位置
org[x].erase(t);
}
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++) //初始化
{
org[i].push_back(i);
rec[i]=i;
}
int a,b;
string s1,s2;
while(cin>>s1){
if(s1=="quit")
break;
cin>>a>>s2>>b;
if(s1=="move"){
if(s2=="onto"){
int x=rec[a];
// auto p=restore(a);
vector<int>::iterator p=restore(a);
restore(b);
org[rec[b]].push_back(a);
rec[a]=rec[b];
org[x].erase(p);
// org[x].pop_back();
}
else{
int x=rec[a];
vector<int>::iterator p=restore(a);
restore(a);
org[rec[b]].push_back(a);
rec[a]=rec[b];
org[x].erase(p);
// org[x].pop_back();
}
}
else
{
if(s2=="onto"){
restore(b);
piles_move(a,b);
}
else
{
piles_move(a,b);
}
}
}
for(int i=0;i<n;i++){
cout<<i<<':';
for(int j=0;j<org[i].size();j++)
cout<<' '<<org[i][j];
cout<<endl;
}
return 0;
}
C - Babelfish
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.
題意:有本詞典,要求你將輸入的外語轉化成英語
輸入的格式不好控制,以下程式碼中解決方式來自於:https://blog.csdn.net/qq_38570571/article/details/81035319
程式碼中涉及到的sscanf()可以參考:https://www.cnblogs.com/jiading/p/10800107.html
程式碼:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
#define N 50005
#define PI acos(-1.0)
#define reset(x) memset(x,0,sizeof(x))
typedef long long int ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
char str[500],s1[500],s2[500];
map<string,string>dic;
while (gets(str)&&str[0]!='\0')
{
sscanf(str,"%s %s",s1,s2); //sscanf()以固定字串為輸入源。
dic[s2]=s1;
}
while(gets(str)){
if(dic.find(str)!=dic.end()){
cout<<dic[str]<<endl;
}
else cout<<"eh"<<endl;
}
return 0;
}
D - Ananagrams
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
題意:輸入一本詞典,找出詞典中一旦移動順序就組不成單詞的詞(組不成單詞是指在輸入詞典中找不到相同的詞,且不區分大小寫)
程式碼:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
#define N 50005
#define PI acos(-1.0)
#define reset(x) memset(x,0,sizeof(x))
typedef long long int ll;
string change(string s){
for(int i=0;i<s.size();i++)
{
if(s[i]>='A'&&s[i]<='Z'){
s[i]=s[i]+32;
}
}
sort(s.begin(),s.end());
return s;
}
bool cmp(pair<string,string>a1,pair<string,string>a2)
{
return a1.first<a2.first;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
string str;
map<string,int>dic;
vector<pair<string,string>> ori;
while (cin>>str&&str!="#")
{
string tmp=change(str);
ori.push_back(pair<string,string>(str,tmp));
dic[tmp]++;
}
sort(ori.begin(),ori.end(),cmp);
for(int i=0;i<ori.size();i++){
if(dic[ori[i].second]<=1){
cout<<ori[i].first<<endl;
}
}
return 0;
}
E - Concatenation of Languages
A language is a set of strings. And the concatenation of two languages is the set of all strings that
are formed by concatenating the strings of the second language at the end of the strings of the first
language.
For example, if we have two language A and B such that:
A = {cat, dog, mouse}
B = {rat, bat}
The concatenation of A and B would be:
C = {catrat, catbat, dograt, dogbat, mouserat, mousebat}
Given two languages your task is only to count the number of strings in the concatenation of the
two languages.
Input
There can be multiple test cases. The first line of the input file contains the number of test cases, T
(1 ≤ T ≤ 25). Then T test cases follow. The first line of each test case contains two integers, M and
N (M, N < 1500), the number of strings in each of the languages. Then the next M lines contain the
strings of the first language. The N following lines give you the strings of the second language. You
can assume that the strings are formed by lower case letters (‘a’ to ‘z’) only, that they are less than
10 characters long and that each string is presented in one line without any leading or trailing spaces.
The strings in the input languages may not be sorted and there will be no duplicate string.
Output
For each of the test cases you need to print one line of output. The output for each test case starts
with the serial number of the test case, followed by the number of strings in the concatenation of the
second language after the first language.
Sample Input
2
3 2
cat
dog
mouse
rat
bat
1 1
abc
cab
Sample Output
Case 1: 6
Case 2: 1
題意:輸入A、B兩種語言,將B中每個單詞接在A中每一個單詞後面,所有形成的新單詞構成的集合為C語言,求C語言中單詞個數
一切正常,除了出題人腦子有坑外,題目給你說好輸入的是小寫字母,結果他的測試資料輸入裡面有空行…
程式碼:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 50005;
const double PI = acos(-1.0);
#define reset(x) memset(x,0,sizeof(x))
typedef long long int ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
int index=1;
while(n--){
int a,b;
cin>>a>>b;
set<string> all_s;
vector<string> s1;
vector<string> s2;
string s;
getline(cin,s);
for(int i=0;i<a;i++)
{
// cin>>s;
getline(cin,s);
if(s[0]==' ')
s[0]='\0';
s1.push_back(s);
}
for(int i=0;i<b;i++)
{
getline(cin,s);
// cin>>s;
if(s[0]==' ')
s[0]='\0';
s2.push_back(s);
}
for(int i=0;i<s1.size();i++)
for(int j=0;j<s2.size();j++)
{
all_s.insert(s1[i]+s2[j]);
}
cout<<"Case "<<index<<": "<<all_s.size()<<endl;
index++;
}
return 0;
}
F - The Spot Game
The game of Spot is played on an N × N board as shown below for N = 4. During the game, alternate
players may either place a black counter (spot) in an empty square or remove one from the board, thus
producing a variety of patterns. If a board pattern (or its rotation by 90 degrees or 180 degrees) is
repeated during a game, the player producing that pattern loses and the other player wins. The game
terminates in a draw after 2N moves if no duplicate pattern is produced before then.
Consider the following patterns:
If the first pattern had been produced earlier, then any of the following three patterns (plus one
other not shown) would terminate the game, whereas the last one would not.
Input
Input will consist of a series of games, each consisting of the size of the board, N (2 ≤ N ≤ 50)
followed, on separate lines, by 2N moves, whether they are all necessary or not. Each move will consist
of the coordinates of a square (integers in the range 1…N) followed by a blank and a character ‘+’ or ‘-’
indicating the addition or removal of a spot respectively. You may assume that all moves are legal, that
is there will never be an attempt to place a spot on an occupied square, nor to remove a non-existent
spot. Input will be terminated by a zero (0).
Output
Output will consist of one line for each game indicating which player won and on which move, or that
the game ended in a draw. See the Sample Output below for the exact format.
Sample Input
2
1 1 +
2 2 +
2 2 -
1 2 +
2
1 1 +
2 2 +
1 2 +
2 2 -
0
Sample Output
Player 2 wins on move 3
Draw
題意:兩個人輪流操作,可以選擇下棋或是刪掉棋盤上的某顆棋子,在某人操作完後若棋局與之前出現過的重複則對手獲勝;
程式碼:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 50005;
const double PI = acos(-1.0);
#define reset(x) memset(x,0,sizeof(x))
typedef long long int ll;
string rotates(string &s,int n){
string t(n*n,'0');
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int x=j;
int y=n-i-1;
t[x*n+y]=s[i*n+j];
}
return t;
}
int change(int i,int j,char c,int n,string &s){
if(c=='+')
s[n*i+j]='1';
else
s[n*i+j]='0';
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(cin>>n&&n){
map<string,bool> spot;
int a,b,f=0;
char c;
string inp(n*n,'0');
string t1,t2,t3;
for(int i=1;i<=2*n;i++)
{
cin>>a>>b>>c;
if(f==0){
change(a-1,b-1,c,n,inp);
t1=rotates(inp,n); //依次旋轉90度
t2=rotates(t1,n);
t3=rotates(t2,n);
if(spot[inp]||spot[t1]||spot[t2]||spot[t3])
f=i;
else
spot[inp]=spot[t1]=spot[t2]=spot[t3]=true;
}
}
if(f)
{
if(f%2)
cout<<"Player 2 wins on move "<<f<<endl;
else
cout<<"Player 1 wins on move "<<f<<endl;
}
else
cout<<"Draw"<<endl;
}
return 0;
}
G - Conformity
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
題意:找出選課組合相同的學生人數最多的那一種組合學生的人數(若如果有兩種組合的人數相等,那麼需要把結果加起來)
(用map的程式碼在POJ上提交TLE…,在UVA上通過)
(POJ TLE,UVA AC)程式碼:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 50005;
const double PI = acos(-1.0);
#define reset(x) memset(x,0,sizeof(x))
typedef long long int ll;
string rotates(string &s,int n){
string t(n*n,'0');
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
int x=j;
int y=n-i-1;
t[x*n+y]=s[i*n+j];
}
return t;
}
int change(int i,int j,char c,int n,string &s){
if(c=='+')
s[n*i+j]='1';
else
s[n*i+j]='0';
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(cin>>n&&n){
int maxc_n=0,maxc=-1;
map<set<int>,int>all_stu;
for(int i=0;i<n;i++){
set<int> course;
for(int j=0;j<5;j++)
{
int num;
cin>>num;
course.insert(num);
}
all_stu[course]++;
if(all_stu[course]>maxc){
maxc=all_stu[course];
maxc_n=1;
}
else if(all_stu[course]==maxc){
maxc_n++;
}
}
cout<<maxc_n*maxc<<endl;
}
return 0;
}
AC程式碼:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 10005;
const double PI = acos(-1.0);
#define reset(x) memset(x,0,sizeof(x))
typedef long long int ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(cin>>n&&n){
int all_stu[N];
// memset(all_stu,0,sizeof(all_stu));
for(int i=0;i<n;i++){
int course[5];
for(int j=0;j<5;j++)
cin>>course[j];
sort(course,course+5); //防止選課順序不同的影響
int tval=0;
for(int j=0;j<5;j++)
{
tval*=100;
tval+=course[j];
}
all_stu[i]=tval;
}
sort(all_stu,all_stu+n);
all_stu[n]=-1;
int maxval=0,min=1,l=0;
int res[N];
for(int i=0;i<n;i++){
if(all_stu[i]==all_stu[i+1]){
min++;
}
else{
res[l++]=min;
maxval=max(maxval,min);
min=1;
}
}
int ans=0;
for(int i=0;i<l;i++)
if(res[i]==maxval) ans+=maxval;
cout<<ans<<endl;
}
return 0;
}