pta天梯训练赛补题

7-1谁先倒

划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。

下面给出甲、乙两人的酒量(最多能喝多少杯不倒)和划拳记录,请你判断两个人谁先倒。

输入格式:

输入第一行先后给出甲、乙两人的酒量(不超过100的非负整数),以空格分隔。下一行给出一个正整数N≤),随后N行,每行给出一轮划拳的记录,格式为:

甲喊 甲划 乙喊 乙划
 

其中是喊出的数字,是划出的数字,均为不超过100的正整数(两只手一起划)。

输出格式:

在第一行中输出先倒下的那个人:A代表甲,B代表乙。第二行中输出没倒的那个人喝了多少杯。题目保证有一个人倒下。注意程序处理到有人倒下就终止,后面的数据不必处理。

输入样例:

1 1
6
8 10 9 12
5 10 5 10
3 8 5 12
12 18 1 13
4 16 12 15
15 1 1 16
 

输出样例:

A
1
#include<bits/stdc++.h>
using namespace std;
int main()
{
   int a,b;
   cin>>a>>b;
   int n,x=0,y=0;
   cin>>n;
   while(n--)
   {
       int ah,al,bh,bl;
       cin>>ah>>al>>bh>>bl;
       if(al==(ah+bh)&&bl!=((ah+bh)))
       {
           x++;
           a--;
           if(a==-1)
           {
               cout<<"A"<<endl;
               cout<<y<<endl;
               break;
           }
       }
       else if(bl==(ah+bh)&&al!=(ah+bh))
       {
           y++;
           b--;
           if(b==-1)
           {
               cout<<"B"<<endl;
               cout<<x<<endl;
           }
       }
       else continue;
   }
}

7-6情人节

 

 

 

以上是朋友圈中一奇葩贴:“2月14情人节了,我决定造福大家。第2个赞和第14个赞的,我介绍你俩认识…………咱三吃饭…你俩请…”。现给出此贴下点赞的朋友名单,请你找出那两位要请客的倒霉蛋。

输入格式:

输入按照点赞的先后顺序给出不知道多少个点赞的人名,每个人名占一行,为不超过10个英文字母的非空单词,以回车结束。一个英文句点.标志输入的结束,这个符号不算在点赞名单里。

输出格式:

根据点赞情况在一行中输出结论:若存在第2个人A和第14个人B,则输出“A and B are inviting you to dinner...”;若只有A没有B,则输出“A is the only one for you...”;若连A都没有,则输出“Momo... No one is for you ...”。

输入样例1:

GaoXZh
Magi
Einst
Quark
LaoLao
FatMouse
ZhaShen
fantacy
latesum
SenSen
QuanQuan
whatever
whenever
Potaty
hahaha
.
 

输出样例1:

Magi and Potaty are inviting you to dinner...
 

输入样例2:

LaoLao
FatMouse
whoever
.
 

输出样例2:

FatMouse is the only one for you...
 

输入样例3:

LaoLao
.
 

输出样例3:

Momo... No one is for you ...

 

#include<bits/stdc++.h>
#include<string>
#include<cstdio>
using namespace std;
#define maxn 10000000
int main()
{
    int ct=0,i;
    string s,a="0",b="0";
    while(cin>>s)
    {
        if(s==".")break;
        ++ct;
        //cout<<ct<<endl;
        if(ct==2)
        {
            a=s;
            //cout<<s<<" "<<a<<endl;
        }
        else if(ct==14)
        {
            b=s;
        }

    }
    if(ct<2)//要注意是从第二个人开始,一开始弄成了一个人也没有的情况了,一个人时也符合
    cout<<"Momo... No one is for you ..."<<endl;
    else if(a!="0"&&b=="0")cout<<a<<" is the only one for you..."<<endl;
    else if(a!="0"&&b!="0")cout<<a<<" and "<<b<<" are inviting you to dinner..."<<endl;
}

 

7-9排座位

布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。

输入格式:

输入第一行给出3个正整数:N≤100),即前来参宴的宾客总人数,则这些人从1到N编号;M为已知两两宾客之间的关系数;K为查询的条数。随后M行,每行给出一对宾客之间的关系,格式为:宾客1 宾客2 关系,其中关系为1表示是朋友,-1表示是死对头。注意两个人不可能既是朋友又是敌人。最后K行,每行给出一对需要查询的宾客编号。

这里假设朋友的朋友也是朋友。但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的。

输出格式:

对每个查询输出一行结果:如果两位宾客之间是朋友,且没有敌对关系,则输出No problem;如果他们之间并不是朋友,但也不敌对,则输出OK;如果他们之间有敌对,然而也有共同的朋友,则输出OK but...;如果他们之间只有敌对关系,则输出No way

输入样例:

7 8 4
5 6 1
2 7 -1
1 3 1
3 4 1
6 7 -1
1 2 1
1 4 1
2 3 -1
3 4
5 7
2 3
7 2
 

输出样例:

No problem
OK
OK but...
No way

题解:用二维数组带入宾客编号,分别赋值为1,-1,0表示朋友,敌人,陌生人,是朋友,且没有敌对关系,则输出No problem;如果他们之间并不是朋友,但也不敌对,则输出OK;如果他们之间有敌对,然而也有共同的朋友,则输出OK but...;如果他们之间只有敌对关系,则输出No way只有单纯直接的敌对关系才是绝对不能同席的。

#include<bits/stdc++.h>
#include<string>
#include<cstdio>
using namespace std;
int main()
{

    int n,m,k,s[110][110]={0};
    cin>>n>>m>>k;
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        s[a][b]=c;
        s[b][a]=c;
    }
    for(int i=1;i<=k;i++)
    {
        int x,y;
        cin>>x>>y;
        if(s[x][y]==1||s[y][x]==1)cout<<"No problem"<<endl;
        else if(s[x][y]==0||s[y][x]==0)cout<<"OK"<<endl;
        else
        {
            int p=0;
            for(int j=1;j<=n;j++)
            {
                if(s[j][x]*s[j][y]==1)
                {
                    p=1;
                    cout<<"OK but..."<<endl;
                    break;
                }
            }
            if(p==0)cout<<"No way"<<endl;
            //else if((k==0&&s[x][y]!=-1)||(k==0&&s[y][x]!=-1))cout<<"OK"<<endl;
        }
    }



}

 

7-10最长对称子串

对给定的字符串,本题要求你输出最长对称子串的长度。例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11。

输入格式:

输入在一行中给出长度不超过1000的非空字符串。

输出格式:

在一行中输出最长对称子串的长度。

输入样例:

Is PAT&TAP symmetric?
 

输出样例:

11

题解:输入要用getline(cin,str),先对称着看两边的字符是否相等,如果相等则截取该段字符串同时记下该段长度,再重新查看是否是对称的,如果不是则返回继续找。

#include<bits/stdc++.h>
using namespace std;
int show(string s)
{
    for(int i=0;i<s.size();i++)
    {
        if(s[i]==s[s.size()-1-i])
        {
            continue;

        }
        else return 0;
    }
    return 1;
}
int main()
{
    string s,b;
    getline(cin,s);
    int m=s.size(),n;
    int i,j,ct=0,k=m-1;
    for(i=0;i<m;i++){
        for(j=m-1;j>=i;j--){
            if(s[i]==s[j])
            {
               b=s.substr(i,j-i+1);//从i开始截取长度为j-i+1的字符串
               if(show(b)==1)
               {
                   n=b.size();
                   ct=max(ct,n);//选取最长的长度
               }
               else continue;
            }
        }
    }
    cout<<ct<<endl;
}

 

7-11重排链表

给定一个单链表 L1​​→L2​​→⋯→Ln1​​→Ln​​,请编写程序将链表重新排列为 Ln​​→L1​​→Ln1​​→L2​​→⋯。例如:给定L为1→2→3→4→5→6,则输出应该为6→1→5→2→4→3。

输入格式:

每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数,即正整数N (≤)。结点的地址是5位非负整数,NULL地址用−表示。

接下来有N行,每行格式为:

Address Data Next
 

其中Address是结点地址;Data是该结点保存的数据,为不超过1的正整数;Next是下一结点的地址。题目保证给出的链表上至少有两个结点。

输出格式:

对每个测试用例,顺序输出重排后的结果链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 6
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
 

输出样例:

68237 6 00100
00100 1 99999
99999 5 12309
12309 2 00000
00000 4 33218
33218 3 -1
 题解:建立结点的结构体,输入结点地址及数据,还有下一个结点的地址,根据首地址再依次将结点存入另一个数组中,最后根据题意格式输出
#include<vector>
#include<bits/stdc++.h>
using namespace std;
const int N =100000;
struct Node
{
    int ad;
    int data;
    int next;
}s[N];
int main()
{
    vector <Node> b;
    int i,f,n,j,k,x,y,z,m;
    cin>>f>>n;
    for(i=0;i<n;i++)
    {
        cin>>x>>y>>z;
        s[x].ad=x;
        s[x].data=y;
        s[x].next=z;
    }
    while(f!=-1)
    {
        b.push_back(s[f]);//第一个为首地址
        f=s[f].next;
        /*   00100   1  12309
    next     12309   2  33218
             33218   3  00000
             00000   4  99999
             99999   5  68237
             68237   6  00100
             -1

        */
    }
    m=b.size();
    for(i=0;i<m/2;i++)
    {
        printf("%05d %d %05d\n",b[m-i-1].ad,b[m-i-1].data,b[i].ad);
        if(i==m/2-1&&m%2==0)printf("%05d %d -1\n",b[i].ad,b[i].data);
        else printf("%05d %d %05d\n",b[i].ad,b[i].data,b[m-i-2].ad);
    }
    if(m%2!=0)printf("%05d %d -1\n",b[m/2].ad,b[m/2].data);
}

 

7-12分而治之

分而治之,各个击破是兵家常用的策略之一。在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破。为此参谋部提供了若干打击方案。本题就请你编写程序,判断每个方案的可行性。

输入格式:

输入在第一行给出两个正整数 N 和 M(均不超过10 000),分别为敌方城市个数(于是默认城市从 1 到 N 编号)和连接两城市的通路条数。随后 M 行,每行给出一条通路所连接的两个城市的编号,其间以一个空格分隔。在城市信息之后给出参谋部的系列方案,即一个正整数 K (≤ 100)和随后的 K 行方案,每行按以下格式给出:

Np v[1] v[2] ... v[Np]
 

其中 Np 是该方案中计划攻下的城市数量,后面的系列 v[i] 是计划攻下的城市编号。

输出格式:

对每一套方案,如果可行就输出YES,否则输出NO

输入样例:

10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 10
2 4
5
4 10 3 8 4
6 6 1 7 5 4 9
3 1 8 4
2 2 8
7 9 8 7 6 5 4 2
 

输出样例:

NO
YES
YES
NO
NO
题意:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,i,j,s[N],b[N];
int p[N],k,w,v;
int main()
{

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>s[i]>>b[i];
    }
    cin>>k;
    while(k--)
    {
        cin>>w;

        memset(p,0,sizeof(p));
        for(i=0;i<w;i++)
        {
            int v;
            cin>>v;
            p[v]=1;//把要攻占的城市编号所表示的值设为1
        }
        bool q=true;
        for(j=1;j<=m;j++){
                cout<<p[s[j]]<<" "<<p[b[j]];
            if(p[s[j]]==1||p[b[j]]==1)//只要两个相同的城市中一个道路被断则成立
            {
               ;
            }
            else
            {
                q=false;
                break;
            }
        }
        if(q)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

 

posted @ 2020-10-10 22:27  西瓜0  阅读(138)  评论(0)    收藏  举报