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

**

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.
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的区域(初始时区域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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值