ACM集训周记(二)

第二周(7.18-7.124)

1.函数和递归练习

6-6 求组合数(高效递归版)

请编写高效递归函数,求组合数。

函数原型

double Cmb(int x, int y);

说明:x 和 y 为非负整数,且 x ≥ y ≥ 0,函数值为组合数 Cxy​。

要求:不要使用循环语句,不调用阶乘函数和排列数函数。找出最快的递推公式,该函数直接调用自己求得结果。

裁判程序

#include <stdio.h>

double Cmb(int x, int y);

int main()
{
    int m, n;
    scanf("%d%d", &m, &n);
    printf("%.10g\n", Cmb(m, n));
    return 0;
}

/* 你提交的代码将被嵌在这里 */

输入样例

4 2 

 输出样例

6

测试数据

输入样例输出样例
0 01
5 01
34 172333606220
160 15812720
1000 100

6.385051193e+139

代码:

double Cmb(int x, int y)
{
	double num;
	if(x<0||y<0||y>x)
	return 0;
	else if(y==0)
	return 1;   //递归的结束条件
	else if((y*2)>x){//将m-n进行简化(数学学过(高中知识),你可以搜一下)的判断
                     //判断的方法有很多如(y>(x/2))只要你找到即可
		y=x-y;
		num=Cmb(x,y);
	}else{
		num=(double)x*Cmb(x-1,y-1)/y;
//递归一定要找到公式(自己通过规律找,如果是错的那就接着找)
//找的是所求的解与前面几项的关系(类似于数学中的通项公式)
 
	}
	return num;
}

 6-9 重复显示字符(增强递归版)

请编写递归函数,重复显示字符。

void ShowHollow(int number, char symbol, int hollow);

说明:参数 number 为重复次数,symbol 为显示字符,hollow 为空心标记。若 hollow 为 0(假),函数将在屏幕上重复显示 number 个 symbol 字符。若 hollow 为 1(真),则输出的 number 个字符中,只有首字符和末字符为 symbol 字符,中间的字符均为空格(即空心)。若 number 小于等于 0,则不输出。

要求:不要使用循环语句。

提示:可增加自用的内部函数。

裁判程序

#include <stdio.h>

void ShowHollow(int number, char symbol, int hollow);

int main()
{
    int n, h;
    char s;
    scanf("%d %c %d", &n, &s, &h);
    ShowHollow(n, s, h);
    putchar('\n');
    return 0;
}

/* 你提交的代码将被嵌在这里 */

输入样例1

-3 @ 0

输出样例1

注:无输出

输入样例2

1 @ 1

输出样例2

@

输入样例3

2 @ 0

输出样例3

@@

输入样例4

5 @ 1

输出样例4

@   @

输入样例5

8 @ 0

输出样例

@@@@@@@@

代码: 


int x = 1; //只输出第一个符号的标记
void ShowHollow(int number, char symbol, int hollow){
    if(number<=0){
        x = 1;     //递归结束,标记重置
        return 0;
    }
    if(hollow==0){  //输出number个符号的情况
        printf("%c", symbol);
        ShowHollow(number - 1, symbol, hollow);
    }
    else{       //首尾输出符号的情况
        if(number==1){    //输出尾部符号
            printf("%c", symbol);
            return 0;
        }
        else{
            if(x==1){     //输出第一个符号
                printf("%c", symbol);
                x--;
            }
            else{
                printf(" ");   //输出中间空格
            }
            ShowHollow(number - 1, symbol, hollow);
        }
    }
}

A - 古老的密码

Ancient Roman empire had a strong government system with various departments, including a secret service department. Important documents were sent between provinces and the capital in encrypted form to prevent eavesdropping. The most popular ciphers in those times were so called substitution cipher and permutation cipher.

        Substitution cipher changes all occurrences of each letter to some other letter. Substitutes for all letters must be different. For some letters substitute letter may coincide with the original letter. For example, applying substitution cipher that changes all letters from ‘A’ to ‘Y’ to the next ones in the alphabet, and changes ‘Z’ to ‘A’, to the message “VICTORIOUS” one gets the message “WJDUPSJPVT”.

        Permutation cipher applies some permutation to the letters of the message. For example, applying the permutation 〈2, 1, 5, 4, 3, 7, 6, 10, 9, 8〉 to the message “VICTORIOUS” one gets the message “IVOTCIRSUO”.

         It was quickly noticed that being applied separately, both substitution cipher and permutation cipher were rather weak. But when being combined, they were strong enough for those times. Thus, the most important messages were first encrypted using substitution cipher, and then the result was encrypted using permutation cipher. Encrypting the message “VICTORIOUS” with the combination of the ciphers described above one gets the message “JWPUDJSTVP”.

        Archeologists have recently found the message engraved on a stone plate. At the first glance it seemed completely meaningless, so it was suggested that the message was encrypted with some substitution and permutation ciphers. They have conjectured the possible text of the original message that was encrypted, and now they want to check their conjecture. They need a computer program to do it, so you have to write one

Input

Input file contains several test cases. Each of them consists of two lines. The first line contains the message engraved on the plate. Before encrypting, all spaces and punctuation marks were removed, so the encrypted message contains only capital letters of the English alphabet. The second line contains the original message that is conjectured to be encrypted in the message on the first line. It also contains only capital letters of the English alphabet.

        The lengths of both lines of the input file are equal and do not exceed 100.

Output

For each test case, print one output line. Output ‘YES’ if the message on the first line of the input file could be the result of encrypting the message on the second line, or ‘NO’ in the other case.

Sample Input

JWPUDJSTVP

VICTORIOUS

MAMA

ROME

HAHA

HEHE

AAA

AAA

NEERCISTHEBEST

SECRETMESSAGES

Sample Output

YES

NO

YES

YES

NO

题意:输入字符串s,t,判断t是否能通过s加密得到,加密方法为先将某个字母替换为另一个任意字母,然后打乱顺序

思路:只需要检查两个字符串中字母数量关系是否一样,如:

        AABBC    221        UUOPP    212

        将两组数据排序后都为 122  即输出YES

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int c[26], b[26];   //哈希表,存放字母数量
bool cmp(int a,int b){
    return a > b;
}
int main(){
    string s,t;
    while(cin>>s>>t){
        int n=0,m=0;
        memset(c, 0, sizeof(c));
        memset(b, 0, sizeof(b));
        int len = s.size();
        for (int i = 0; i < len;i++){   //把字母数量存进哈希表
            c[s[i] - 'A']++;
            b[t[i] - 'A']++;
        }
        sort(c, c + 26, cmp);     //降序排序,有效数字排到前面
        sort(b, b + 26, cmp);
        int f = 0;
        for (int j = 0; j < 26;j++){   //判断是否一一对应
            if(c[j]!=b[j]){
                f = 1;
                break;
            }
        }
        if(f==0)
            cout << "YES" << endl;
        else
            cout << "NO"<<endl;
    }
    return 0;
}

B - 刽子手游戏

In “Hangman Judge,” you are to write a program that judges a series of Hangman games. For each game, the answer to the puzzle is given as well as the guesses. Rules are the same as the classic game of hangman, and are given as follows:

        1. The contestant tries to solve to puzzle by guessing one letter at a time.

        2. Every time a guess is correct, all the characters in the word that match the guess will be “turned over.” For example, if your guess is ‘o’ and the word is “book”, then both ‘o’s in the solution will be counted as “solved”.

        3. Every time a wrong guess is made, a stroke will be added to the drawing of a hangman, which needs 7 strokes to complete. Each unique wrong guess only counts against the contestant once

        4. If the drawing of the hangman is completed before the contestant has successfully guessed all the characters of the word, the contestant loses.

         5. If the contestant has guessed all the characters of the word before the drawing is complete, the contestant wins the game.

         6. If the contestant does not guess enough letters to either win or lose, the contestant chickens out.

        Your task as the “Hangman Judge” is to determine, for each game, whether the contestant wins, loses, or fails to finish a game.

Input

Your program will be given a series of inputs regarding the status of a game. All input will be in lower case. The first line of each section will contain a number to indicate which round of the game is being played; the next line will be the solution to the puzzle; the last line is a sequence of the guesses made by the contestant. A round number of ‘-1’ would indicate the end of all games (and input).

Output

The output of your program is to indicate which round of the game the contestant is currently playing as well as the result of the game. There are three possible results:

You win.

You lose.

You chickened out.

Sample Input

1

cheese

chese

2

cheese

abcdefg

3

cheese

abcdefgij

-1

Sample Output

Round 1

You win.

Round 2

You chickened out.

Round 3

You lose.

游戏规则:

        计算机想一个单词让你猜,你每次可以猜一个字母,如果单词里有那个字母,所有该              字母都会显示出来,如果没有那个字母则计算机会在一副“刽子手”画上填一笔,这幅画一共需要7笔就能完成,因此你最多只能错6次。注意猜一个已经猜过的字母也算错。         

         在本题中,你的任务是编写一个“裁判”程序,输入单词和玩家的猜测,判断玩家赢了,(You win.)、输了(You lose.)、还是放弃了(You chickened out.)
        每组包含3行,第一行是游戏编号(-1为输入结束标记),第2行是计算机想的单词,第3行是玩家的猜测。后两行保证只含小写字母。

思路:

        因为猜中一个字母就会翻开所有字母,所以重复的字母只用存一次,可以用set来存放目标单词,读入玩家猜的字符串t,逐个判断t[i]是否在set中,找到的话就删除set中的这个字母,下次再猜这个字母就会视为猜错,因为这个字母已经从set中删除,找不到。最后做三个判断输出结果。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;

int main(){
    string s, t;
    int x;
    while(cin>>x>>s>>t){       
        if(x==-1)
            break;
        int n = 6;     //标记猜错次数,猜错一次就-1
        set<char> a;   //存放目标单词
        for (int i = 0; i < s.size();i++)  //把s存进set,自动去重
            a.insert(s[i]);
        for (int i = 0; i < t.size();i++){  //逐个判断
            if(a.find(t[i])==a.end()){      //set中找不到t[i],猜错一次
                n--;
            }
            a.erase(t[i]);  //set中存在t[i],就会删除,不存在不印象
            if(a.size()==0)
                break;      //游戏结束提前跳出循环
        }
        // cout << a.size() <<" "<<n<< endl;
        if(a.size()==0&&n>=0){
            printf("Round %d\nYou win.\n",x);
        }
        if(a.size()!=0&&n>=0){
            printf("Round %d\nYou chickened out.\n",x);
        }
        if(n<0){
            printf("Round %d\nYou lose.\n",x);
        }
    }
    return 0;
}

C - 救济金发放

In a serious attempt to downsize (reduce) the dole queue, The New National Green Labour Rhinoceros Party has decided on the following strategy. Every day all dole applicants will be placed in a large circle, facing inwards. Someone is arbitrarily chosen as number 1, and the rest are numbered counterclockwise up to N (who will be standing on 1’s left). Starting from 1 and moving counter-clockwise, one labour official counts off k applicants, while another official starts from N and moves clockwise, counting m applicants. The two who are chosen are then sent off for retraining; if both officials pick the same person she (he) is sent off to become a politician. Each official then starts counting again at the next available person and the process continues until no-one is left. Note that the two victims (sorry, trainees) leave the ring simultaneously, so it is possible for one official to count a person already selected by the other official

Input

Write a program that will successively read in (in that order) the three numbers (N, k and m; k, m > 0, 0 < N < 20) and determine the order in which the applicants are sent off for retraining. Each set of three numbers will be on a separate line and the end of data will be signalled by three zeroes (0 0 0

Output

For each triplet, output a single line of numbers specifying the order in which people are chosen. Each number should be in a field of 3 characters. For pairs of numbers list the person chosen by the counterclockwise official first. Separate successive pairs (or singletons) by commas (but there should not be a trailing comma).

Note: The symbol ⊔ in the Sample Output below represents a space.

Sample Input

10 4 3

0 0 0

Sample Output

␣␣4␣␣8,␣␣9␣␣5,␣␣3␣␣1,␣␣2␣␣6,␣10,␣␣7

题意:假定N个人从1-N逆时针编号,Rk从1开始逆时针数k个人,Rm从n开始顺时针数m个人,淘汰被选中的人,依次类推,直至最后无人存活

思路:双向约瑟夫环,

  • 使用标记0和1来表示选中的人和没有选中的人,逻辑清晰。
  • 相比较笨拙的for前后模拟,这种方法抽象出了函数,其中用+1和-1来表示顺/逆,值得学习。
  • 约瑟夫环公式:p = (p + d + n - 1) % n + 1

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n, k, m, a[25];
 
int go(int p, int d, int t)
{
    while(t--)
    {
        do
        {
            p = (p + d + n - 1) % n + 1;
        }while(a[p] == 0);//走到下一个非零的数字
    }
    return p;
}
 
int main(){
    while(scanf("%d%d%d", &n, &k, &m) == 3 && (n != 0 && k != 0 && m != 0))
    {
        for(int i = 1; i <= n; i++)
            a[i] = i;
        int left = n;
        int p1 = n, p2 = 1;
        while(left)
        {
            p1 = go(p1, 1, k);
            p2 = go(p2, -1, m);
            printf("%3d", p1);
            left--;
            if(p2 != p1)
            {
                printf("%3d", p2);
                left--;
            }
            a[p1] = a[p2] = 0;
            if(left)
                printf(",");
        }
        printf("\n");
    }
	return 0;
}

2.STL练习

问题 B: 括弧匹配检验

       假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,如([]())或[([][])]等为正确的匹配,[(])或([]()或(()))均为错误的匹配。

现在的问题是,要求检验一个给定表达式中的括弧是否正确匹配?

输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出 “OK” ,不匹配就输出“Wrong”。

输入一个字符串:[([][])],输出:OK

输入

       输入仅一行字符(字符个数小于255)

输出

匹配就输出 “OK” ,不匹配就输出“Wrong”。

样例输入

[(])

样例输出

Wrong

思路:用栈实现,遇到 '(' 或 '[' 就入栈,遇到 ')' 或 ']' 就检查栈顶元素是否为 '(' 或 '[',是则删除栈顶元素,否则输出NO,最后如果栈为空输出YES

代码:

#include <iostream>
#include <string>
#include<stack>
using namespace std;
int main()
{
    string x;
    string a;
    cin >> x;
    for(int i=0;i<x.size();i++){
        if(x[i]=='('||x[i]=='['){
            a = a + x[i];
        }
        else{
            if(x[i]==')'){
                if(a[a.size()-1]=='(')
                    a.erase(a.end() - 1);
                else{
                    cout << "Wrong";
                    return 0;
                }
            }
            if(x[i]==']'){
                if(a[a.size()-1]=='[')
                    a.erase(a.end() - 1);
                else{
                    cout << "Wrong";
                    return 0;
                }
            }
        }
    }
    if(a.empty())
        cout << "OK";
    else
        cout << "Wrong";
    return 0;
}

问题 C: 字符串匹配问题

字符串中只含有括号 (),[],<>,{},判断输入的字符串中括号是否匹配。如果括号有互相包含的形式,从内到外必须是<>,(),[],{},例如。输入: [()] 输出:YES,而输入([]), ([])都应该输出NO。

输入

第一行为一个整数n,表示以下有多少个由括好组成的字符串。接下来的n行,每行都是一个由括号组成的长度不超过255的字符串

输出

 在输出中有N行,每行都是YES或NO。

样例输入

5
{}{}<><>()()[][]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{<>}{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]
><}{{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]

样例输出

YES
YES
YES
YES
NO

思路:这里的括号要按照一定顺序,不然输出的是NO。那么为了更好的比较每个括号,毕竟这里有8钟括号,所以我们可以用数字来表示他们,这样不仅简便,并且让比较更方便。只要判断读入的括号是否与栈顶的括号相匹配,是则出栈,不是则入栈。
最后判断栈是否被清空就可以了!

代码:

#include <cstring>
#include <iostream>
#include <stack>
#include <string>
using namespace std;
char ss[100000];
int num[100000];
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        cin >> ss;
        for (int i = 0; i < strlen(ss); i++)   //以符号相对应的数字存入数组
        {
            if (ss[i] == '<')
                num[i] = 1;
            else if (ss[i] == '>')
                num[i] = 2;
            else if (ss[i] == '(')
                num[i] = 3;
            else if (ss[i] == ')')
                num[i] = 4;
            else if (ss[i] == '[')
                num[i] = 5;
            else if (ss[i] == ']')
                num[i] = 6;
            else if (ss[i] == '{')
                num[i] = 7;
            else if (ss[i] == '}')
                num[i] = 8;
        }
        stack<int> s;
        bool flag = true;
        for (int i = 0; i < strlen(ss); i++)
        {
            if (s.empty())
                s.push(num[i]);
            else
            {
                if (num[i] % 2 == 1)
                {
                    if (num[i] <= s.top())    //解决括号优先级问题
                        s.push(num[i]);
                    else
                    {
                        flag = false;
                        break;
                    }
                }
                else if (num[i] - 1 == s.top())  //配对的符号相差1
                    s.pop();
            }
        }
        if (s.empty() && flag)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

问题 D: 车厢调度

有一个火车站,铁路如图所示,每辆火车从A驶入,再从B方向驶出,同时它的车厢可以重新组合。假设从A方向驶来的火车有n节(n<=1000),分别按照顺序编号为1,2,3,…,n。假定在进入车站前,每节车厢之间都不是连着的,并且它们可以自行移动到B处的铁轨上。另外假定车站C可以停放任意多节车厢。但是一旦进入车站C,它就不能再回到A方向的铁轨上了,并且一旦当它进入B方向的铁轨,它就不能再回到车站C。

       负责车厢调度的工作人员需要知道能否使它以a1,a2,…,an的顺序从B方向驶出,请来判断能否得到指定的车厢顺序。

输入

输入文件的第一行为一个整数n,其中n<=1000,表示有n节车厢,第二行为n个数字,表示指定的车厢顺序。

输出

如果可以得到指定的车厢顺序,则输出一个字符串”YES”,否则输出”NO”(注意要大写,不包含引号)。

样例输入

5
5 4 3 2 1

样例输出

YES

思路:

观察发现,整个调度过程其实是在模拟入栈出栈的过程,
而这个过程中,我们可以分成三种状态:栈前、栈中、栈后。
可以发现,当某个数字出栈了,说明比它小的数字要么已经出栈了,要么还在栈里,不能是入栈前状态,
并且在栈中的顺序是从大到小的(从栈顶往栈底看),
比如出5,那么1,2,3,4要么已经在5之前出了,要么还在栈中(假如1,3,4在栈中,从栈顶往栈底看依次为4,3,1),不能是入栈前的状态。
如果某个数字要出栈,那么当前在栈中的数字都必须小于它,否则就与栈的性质矛盾,不合法,于是我们可以这样解决:

从第一个数字开始扫描,a[i]表示当前出栈的数字,
如果有比a[i]大的数字还在栈中,那么就产生矛盾,输出“NO”;否则,标记当前数字a[i]为栈后状态,
那么[1, a[i]-1]这些数字如果还没出栈,标记为栈中状态。
具体我们可以用0表示为确定状态,1表示栈中状态,2表示栈后状态。

 

代码:

#include<iostream>
#include<string>
#include<stack>
using namespace std;
int main(){
    stack<int> cz;
    int n;
    int a[1001];
    cin >> n;
    for (int i = 0; i < n;i++){
        cin >> a[i];
    }
    int car = 1;                  
    for (int i = 0; i < n;i++){
    //让车厢按大小顺序入栈,一个车厢想入栈,比它小的要先入栈
        while(car<=a[i])
            cz.push(car++);
        if(a[i]!=cz.top()){   
            cout << "NO";
            return 0;
        }
        else               //栈顶数据弹出,当前的车厢可以出栈了
            cz.pop();
    }
    cout << "YES";
    return 0;
}

 A-圆桌问题

圆桌上围坐着2n个人。其中n个人是好人,另外n个人是坏人。如果从第一个人开始数数,数到第m个人,则立即处死该人;然后从被处死的人之后开始数数,再将数到的第m个人处死……依此方法不断处死围坐在圆桌上的人。试问预先应如何安排这些好人与坏人的座位,能使得在处死n个人之后,圆桌上围坐的剩余的n个人全是好人。

Input

多组数据,每组数据输入:好人和坏人的人数n(<=32767)、步长m(<=32767);

Output

对于每一组数据,输出2n个大写字母,‘G’表示好人,‘B’表示坏人,50个字母为一行,不允许出现空白字符。相邻数据间留有一空行。

Sample

InputcopyOutputcopy
2 3 
2 4
GBBG 
BGGB

思路:

通过计算每次出列的位置pos,进行分类,其中pos=(pos+m-1)%size

通过循环n次将前n个人赶走,且记为坏人,vector中存放的将只有好人,最后遍历vector,相当于重新绕桌子走一圈,位子上没人就输出B,有人就输出G

代码:

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main()
{
    vector < int > table;
    int n,m;
    while(~scanf("%d %d",&n,&m)){
        table.clear();  //清空
        for(int i=0; i<2*n; i++)
            table.push_back(i);  //初始化

        int pos = 0;  //记录当前位置
        for(int i=0; i<n; i++){  //处死n个人
            pos = (pos+m-1) % table.size();
            //圆桌是个环,我们可以认为是很多很多个一样的数组,相邻接着
            table.erase(table.begin() + pos);  //table里把赶走的人去掉,人数减一
        }

        int j = 0;
        for(int i=0; i<2*n; i++){  //打印预先安排的座位
            if(!(i%50) && i)
                //实现50个字母换一行(注意i=0时不应该换行,所以&&i)
                cout<<endl;
            if(j<table.size() && i==table[j]){
                //因为i是从小到大遍历的,
                //而table里的元素我们初始化时包括去掉某些元素,移动过程中,也是保持的从小到大的次序不变的
                //所以可以只是遍历i,自然就是先匹配上较小的table[j]
                j++;
                cout<<"G";  //table中留下的都是好人
            }else
                cout<<"B";
        }
        cout<<endl<<endl;  //相邻数据组间留一个空行
    }
    return 0;
}

3.STL经典例题练习

A - Shopping

Every girl likes shopping,so does dandelion.Now she finds the shop is increasing the price every day because the Spring Festival is coming .She is fond of a shop which is called "memory". Now she wants to know the rank of this shop's price after the change of everyday.

Input

One line contians a number n ( n<=10000),stands for the number of shops.
Then n lines ,each line contains a string (the length is short than 31 and only contains lowercase letters and capital letters.)stands for the name of the shop.
Then a line contians a number m (1<=m<=50),stands for the days .
Then m parts , every parts contians n lines , each line contians a number s and a string p ,stands for this day ,the shop p 's price has increased s.

Output

Contains m lines ,In the ith line print a number of the shop "memory" 's rank after the ith day. We define the rank as :If there are t shops' price is higher than the "memory" , than its rank is t+1.

Sample

InputcopyOutputcopy
3 
memory 
kfc 
wind 
2 
49 
memory 
49 
kfc 
48 
wind 
80 
kfc 
85 
wind 
83 
memory 
1 
2

题意: 输入整数t,随后输入t个店名,再输入n代表天数,随后输入n组,t个店的涨价情况temp

要求输出每一天memory的排名(价格高排名高)

思路:用map的key存店名,value存价格(每天会累积涨价),每天统计排名情况,因为map不能直接用sort排序,所以直接遍历map,遇到比memory的价格高的排名就+1.

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
    map<string, int> m;      //key为店名,value为价格
    string s;
    int t;
    while (cin >> t)
    {
        m.clear();          //有多组数据,必须清空map
        for (int i = 0; i < t; i++)
        {
            cin >> s;
            m.insert(pair<string, int>(s, 0));     //先存入店名,并初始化价格为0
        }
        int n;
        cin >> n;
        while (n--)
        {
            int temp;
            string temps;             //记录当天的涨价数
            for (int i = 0; i < t; i++)
            {
                cin >> temp >> temps;
                m[temps] += temp;     //价格累加
            }
            int index = 0;
            for (auto &c : m)         //当天的统计完,遍历map,计算memory的排名
            {
                if (c.second > m["memory"])
                    index++;
            }
            cout << index + 1 << endl;
        }
    }
    return 0;
}

C - 排列2

Ray又对数字的列产生了兴趣:
现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数。

Input

每组数据占一行,代表四张卡片上的数字(0<=数字<=9),如果四张卡片都是0,则输入结束。

Output

对每组卡片按从小到大的顺序输出所有能由这四张卡片组成的4位数,千位数字相同的在同一行,同一行中每个四位数间用空格分隔。
每组输出数据间空一行,最后一组数据后面没有空行。

Sample

InputcopyOutputcopy
 
1 2 3 4 
1 1 2 3 
0 1 2 3 0 0 0 0 
 
1234 1243 1324 1342 1423 1432 
2134 2143 2314 2341 2413 2431 
3124 3142 3214 3241 3412 3421 
4123 4132 4213 4231 4312 4321 

1123 1132 1213 1231 1312 1321 
2113 2131 2311 
3112 3121 3211 

1023 1032 1203 1230 1302 1320 
2013 2031 2103 2130 2301 2310 
3012 3021 3102 3120 3201 3210 

题意:给定4个数字(乱序)从小到大输出所有排列(格式恶心)

思路:全排列用函数next_petmutation()求

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int a[5], m = 0;
    while (scanf_s("%d%d%d%d", &a[1], &a[2], &a[3], &a[4])){
        if (a[1] == 0 && a[2] == 0 && a[3] == 0 && a[4] == 0) {
            return 0;// 如果四个数都为0时,则输入结束
        }
        if (m) {
            printf("\n");//m=0时,为第一个四位数的第一行,无需换行
        }
        m = 1;
        int h, k = 1;
        do{
            if (a[1] == 0) continue;//如果第一个数为0,则跳过输出,获取下一个排列
            if (k == 1) {//k==1表明是当前四位数的第一个排列,输出时无需有空格
                printf("%d%d%d%d", a[1], a[2], a[3], a[4]);
                k = 0;
            }
            else { //当不是第一个排列时,通过h==a[1]来判断千位数是否与前一个排列的千位数相同
                if (h == a[1]) {//相同,则在同一行中输出,且用空格分开
                    printf(" %d%d%d%d", a[1], a[2], a[3], a[4]);
                }
                else {//不同,则换行输出
                    printf("\n%d%d%d%d", a[1], a[2], a[3], a[4]);
                }
            }
            h = a[1];
        } while (next_permutation(a + 1, a + 5));//利用next_permutation函数获取下一个排列
        printf("\n");
    }
    return 0;
}

F - Andy's First Dictionary

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 sequence of alphabets, in upper and/or lower case. Words with only one letter are also to be considered. Furthermore, your program must be CaSe InSeNsItIvE. 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

 题意:输入一段字符,统计不同单词并升序输出(不区分大小写),每个单词一行

思路:题目要求去重排序,用set存单词,用cin 逐个读入连续字符,然后转小写存入set,遇到 I`m 单独处理。

#include<iostream>
#include<string>
#include<set>
#include<cctype>
using namespace std;

int main(){
    string s;
    set<string> ans;           
    while(cin>>s){                 //逐个读入连续字符
        string temp;
        for (int i = 0; i < s.size();i++){
            if(isalpha(s[i])){
                temp += tolower(s[i]);     //是字母就转小写保存
            }
            else{                          //遇到 I`m I已经存进temp,把I单独加入set
                if(!temp.empty()){         //后面的直接清空
                    ans.insert(temp);
                    temp.clear();
                }
            }
        }
        if(!temp.empty()){                 //把记下来的单词存进Set
            ans.insert(temp);
            temp.clear();
        }
    }
    for(auto &c : ans){
        cout << c << endl;
    }
    return 0;
}

K - 看病要排队

看病要排队这个是地球人都知道的常识。
不过经过细心的0068的观察,他发现了医院里排队还是有讲究的。0068所去的医院有三个医生(汗,这么少)同时看病。而看病的人病情有轻重,所以不能根据简单的先来先服务的原则。所以医院对每种病情规定了10种不同的优先级。级别为10的优先权最高,级别为1的优先权最低。医生在看病时,则会在他的队伍里面选择一个优先权最高的人进行诊治。如果遇到两个优先权一样的病人的话,则选择最早来排队的病人。

现在就请你帮助医院模拟这个看病过程。

Input

输入数据包含多组测试,请处理到文件结束。
每组数据第一行有一个正整数N(0<N<2000)表示发生事件的数目。
接下来有N行分别表示发生的事件。
一共有两种事件:
1:"IN A B",表示有一个拥有优先级B的病人要求医生A诊治。(0<A<=3,0<B<=10)
2:"OUT A",表示医生A进行了一次诊治,诊治完毕后,病人出院。(0<A<=3)

Output

对于每个"OUT A"事件,请在一行里面输出被诊治人的编号ID。如果该事件时无病人需要诊治,则输出"EMPTY"。
诊治人的编号ID的定义为:在一组测试中,"IN A B"事件发生第K次时,进来的病人ID即为K。从1开始编号。

Sample

InputcopyOutputcopy
7 
IN 1 1 I
N 1 2 
OUT 1 O
UT 2 
IN 2 1 
OUT 2 
OUT 1 
2 
IN 1 1 
OUT 1
2 
EMPTY 
3 
1 
1

思路:思路:因为这里有个优先权,所有优先队列很好用,用结构体保存每个病人的编号(id),要看几号医生(n),还有优先权m,然后模拟流程,获取到字符串是IN的话输入 医生和优先权,然后给个编号,因为这里有3个医生,所以用q[4],不是IN就输出,输出首先判断队列是不是空的,空的输出EMPTY,不空输出编号。

#include<iostream>
#include<string>
#include<cstdio>
#include<queue>
using namespace std;
struct node{
    int id;
    int level;
}x;
struct cmp1    //另辟struct,排序自定义,重载优先级
{
	bool operator () (const node & a,const node & b) const{    
    //按优先级排序,优先级相同则按Id从小到大
        if(b.level!=a.level)
        return b.level>a.level;
        else
            return a.id > b.id;
    }
};
int main(){
    int t;
    while(cin>>t){
        priority_queue<node, vector<node>, cmp1> q[4];   //有三个医生,用数组优先队列
        string a;
        int n, m,k=1;
        while(t--){
            cin >> a;
            if(a=="IN"){       
                cin >> n >> m;
                node temp;
                temp.id = k;
                temp.level = m;
                q[n].push(temp);
                k++;
            }
            else{
                cin >> n;
                if(q[n].empty())
                        cout << "EMPTY" << endl;
                else{
                    node num = q[n].top();
                    cout << num.id << endl;
                    q[n].pop();
                }
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值