PAT甲级1001-1030

前言:距离四级考试剩27天,PAT甲级考试剩28天
对PAT甲级练习题做总结

1001 A+B Format (20 分)

  • 题目大意:输入一对整数a,b,计算它们的和,输出格式为3个数字一组
  • 题目解析:把a+b的和转换为字符串输出,从后往前看,下标对3取模,当值为0的时候,后面输出逗号,最后一位不用输出逗号
  • 注意:如果为负号或者最后一位,跳过不用输出逗号
英语单词:

calculate /ˈkælkjuleɪt/ v. 计算,核算;预测,推测
comma /ˈkɒmə/ n. 逗号;停顿

be separated into groups of three by commas
被用逗号分离成3个一组

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1010;

int main(){
    int a,b;cin>>a>>b;
    int sum = a+b;
    string s = to_string(sum);
    int n = s.size();
    for(int i = 0; i < n; i ++ ){
        cout<<s[i];
        if(s[i] == '-' || i == n - 1) continue;
        if((n - 1 - i)%3 == 0) cout<<",";
    }
    return 0;
}

1002 A+B for Polynomials (25 分)

  • 题目大意:输出两个多项式A、B求和,指数相同,系数相加

  • 题目解析:用map容器存多项式,first为指数,second为系数,如果系数为0,则删除它

  • 注意:以输入相同的格式进行输出,从大到小输出

英语单词:

exponents and coefficients 指数和系数
respectively /rɪˈspektɪvli/ adv. 分别地,依次地

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1010;

int n,m;
vector<int> ids;
map<int,double> pol;

int main(){
    cin >> n;
    for(int i = 0; i < n; i ++ ){
        int idx;double val;
        cin >> idx >> val;
        pol[idx] += val;
    }
    cin >> m;
    for(int i = 0; i < m; i ++ ){
        int idx;double val;
        cin >> idx >> val;
        pol[idx] += val;
    }
    for(auto &[k,v] : pol){
        if(pol[k]) ids.push_back(k);
    }
    sort(ids.begin(),ids.end(),greater<>());
    printf("%d",ids.size());
    for(auto id : ids){
        printf(" %d %.1f",id,pol[id]);
    }
    return 0;
}

1003 Emergency (25 分)

  • 题目大意:
    求从当前城市C1到目标城市C2,最短的时间并且召集最多的人,最短路径的条数

  • 题目解析:
    Dijkstra求最短路,第一标尺为距离,第二标尺为点权

核心代码:

初始化:
path[st] = 1;
nums[st] = w[st];

if(dist[j] > dist[t] + g[t][j]){
    dist[j] = dist[t] + g[t][j];
    path[j] = path[t];
    nums[j] = nums[t] + w[j];
}else if(dist[j] == dist[t] + g[t][j]){
    path[j] += path[t];
    if(nums[j] < nums[t] + w[j]){
        nums[j] = nums[t] + w[j];
    }
}
英语单词:

scattered /ˈskætəd/ adj. 分散的;散乱的
mark 做标记,分数
emergency n. 突发事件,紧急情况 adj. 紧急情况下的;应急的
guaranteed /ˌɡærənˈtiːd/ 保证,有保证的

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 510;

int n,m,st,ed;
int g[N][N];
bool vis[N];
int w[N],dist[N],nums[N],path[N];

void dijkstra(){
    memset(dist,0x3f,sizeof dist);
    dist[st] = 0;
    path[st] = 1;
    nums[st] = w[st];
    for(int i = 0; i < n; i ++ ){
        int t = -1;
        for(int j = 0; j < n; j ++ ){
            if(!vis[j] && (t == -1 || dist[t] > dist[j])) t = j;
        }
        vis[t] = true;
        for(int j = 0; j < n; j ++ ){
            if(dist[j] > dist[t] + g[t][j]){
                dist[j] = dist[t] + g[t][j];
                path[j] = path[t];
                nums[j] = nums[t] + w[j];
            }else if(dist[j] == dist[t] + g[t][j]){
                path[j] += path[t];
                if(nums[j] < nums[t] + w[j]){
                    nums[j] = nums[t] + w[j];
                }
            }
        }
    }
}

int main(){
    cin >> n >> m >> st >> ed;
    for(int i = 0; i < n; i ++ ) cin >> w[i];
    memset(g,0x3f,sizeof g);
    for(int i = 0; i < m; i ++ ){
        int a,b,c;cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b],c);
    }
    dijkstra();
    cout<<path[ed]<<" "<<nums[ed];
    return 0;
}

1004 Counting Leaves (30 分)

  • 题目大意:
    给你个树,找每层有几个节点,ojk?

  • 题目解析:
    深搜记录每层没有儿子的节点,并且找出最大层数

英语单词:

seniority /ˌsiːniˈɒrəti/ n. 年长,职位高;资历,年资
represent 代表,象征,表示,表现

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 110;

typedef pair<int,int> pii;

int n,m;
vector<int> v[N];
int ans[N];
int dep;

void dfs(int u,int level){
    if(v[u].size() == 0){
        ans[level] += 1;
        dep = max(dep,level);
    }
    for(auto j : v[u]){
        dfs(j,level+1);
    }
}

int main(){
    cin >> n >> m;
    for(int i = 0; i < m; i ++ ){
        int id,k;cin>>id>>k;
        for(int j = 0; j < k; j ++ ){
            int x;cin>>x;
            v[id].push_back(x);
        }
    }
    dfs(1,1);
    for(int i = 1; i <= dep; i ++){
        if(i - 1) cout<<' ';
        cout<<ans[i];
    }
    return 0;
}

1005 Spell It Right (20 分)

  • 题目大意:
    求给定的非负整数每位数字之和,并用英文输出这个值的每位数字

  • 题目解析:
    值很大,用字符串输入,ojk?

英语单词:

task 作业,任务

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 110;

typedef pair<int,int> pii;

char alp[20][20] = {"zero","one","two","three","four","five","six","seven","eight","nine","ten"};

int main(){
    string s;cin>>s;
    int sum = 0;
    for(auto c : s) sum+=c-'0';
    s = to_string(sum);
    bool flag = false;
    for(auto c : s){
        if(flag) cout<<' ';
        cout<<alp[c-'0'];
        flag = true;
    }
    return 0;
}

1006 Sign In and Sign Out (25 分)

  • 题目大意:
    每天都有人来电脑房,找出第一个开门的和最后一个关门的人。ojk?

  • 题目解析:
    模拟题,时间转换为秒钟计算

英语单词:

moment /ˈməʊmənt/ n. 片刻,瞬间;某一时刻

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 110;

typedef pair<int,int> pii;

int work(string s){
    int st = 0;
    int sum = 0;
    int n = s.size();
    string a = "";
    for(int i = 0; i < n; i ++ ){
        if(s[i] == ':'){
            a = s.substr(st,i-st);
            sum = (sum + stoi(a))*60;
            st = i+1;
        } 
    }
    a = s.substr(st,n - st);
    sum += stoi(a);
    //cout<<a<<endl;
    return sum;
}

int main(){
    int n;cin>>n;
    int mi = 1e9,mx = -1e9;
    string id_mi = "",id_mx = "";
    for(int i = 0; i < n; i ++ ){
        string a,b,c;cin>>a>>b>>c;
        int tim_b = work(b);
        int tim_c = work(c);
        if(mi > tim_b) mi=tim_b,id_mi=a;
        if(mx < tim_c) mx=tim_c,id_mx=a;
    }
    cout<<id_mi<<" "<<id_mx<<endl;
    return 0;
}

1007 Maximum Subsequence Sum (25 分)

英语单词:
代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e5+10;

typedef pair<int,int> pii;

int n;
int a[N],dp[N];
int l[N],r[N];

int main(){
    cin >> n;
    for(int i = 1; i <= n; i ++ ) cin>>a[i],dp[i] = a[i];
    l[0] = r[0] = 1;
    for(int i = 1; i <= n; i ++ ){
        if(dp[i - 1] + a[i] >= dp[i]){
            dp[i] = dp[i - 1] + a[i];
            l[i] = l[i - 1];
            r[i] = i;
        }else{
            l[i] = i,r[i] = i;
        }
    }
    int ans = -1,pos = 1;
    for(int i = 1; i <= n; i ++ ){
        if(dp[i] > ans){
            ans = dp[i];
            pos = i;
        }
    }
    if(ans >= 0) printf("%d %d %d",ans,a[l[pos]],a[r[pos]]);
    else printf("%d %d %d",0,a[1],a[n]);
    return 0;
}

1008 Elevator (20 分)

  • 题目大意:
    从第0层出发,上一层花费6分钟,下一层花费4分钟,停止一次花费5分钟;求这一过程花费总时间。
  • 题目解析:
    模拟题意
英语单词:

denote 表示,指示,意思是
in specified order 按照指定的顺序
fulfill 履行,实现
elevator 电梯
total 总的,合计,全部的

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;

typedef pair<int,int> pii;

int main(){
    int n;cin>>n;
    int sum = 0,last = 0;
    for(int i = 0; i < n; i ++ ){
        int x;cin>>x;
        if(x > last) sum += (x - last)*6 + 5;
        else sum += (last - x)*4 + 5;
        last = x;
    }
    cout<<sum;
    return 0;
}

1009 Product of Polynomials (25 分)

  • 题目大意:
    模拟多项式乘法

  • 题目解析:
    多项式相乘,各项指数相加,系数相乘,ojk?

英语单词:

Please be accurate up to 1 decimal place.
精确到小数点后一位
accurate 准确的,精确的

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;

typedef pair<int,int> pii;

int n,m;
vector<int> ids;
map<int,double> a,b,c;

int main(){
    cin >> n;
    for(int i = 0; i < n; i ++ ){
        int e;double co;cin>>e>>co;
        a.insert({e,co});
    }
    cin >> m;
    for(int i = 0; i < m; i ++ ){
        int e;double co;cin>>e>>co;
        b.insert({e,co});
    }
    for(auto &[k1,v1] : a){
        for(auto &[k2,v2] : b){
            c[k1+k2] += v1*v2;
            if(!c[k1+k2]) c.erase(k1+k2);
        }
    }
    printf("%d",c.size());
    for(auto &[k,v]:c){
        ids.push_back(k);
    }
    sort(ids.begin(),ids.end(),greater<>());
    for(auto id : ids){
        printf(" %d %.1f",id,c[id]);
    }
    return 0;
}

1010 Radix (25 分)

  • 题目大意:

如果tag=1,给出radix是N1的基数,找到另一个基数满足N1=N2,反之亦然

  • 题目解析:
    用二分法找另外一个基数
英语单词:

radix 根,基数

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e5+10;

typedef pair<int,int> pii;
typedef long long LL;

LL convert(string s,LL r){
    LL sum = 0,d = 1;
    int n = s.size();
    for(int i = n - 1; i >= 0; i -- ){
        LL num = isdigit(s[i])?(s[i]-'0'):(s[i] - 'a' + 10);
        sum += d*num;
        d *= r;
    }
    return sum;
}

LL find_decimal(string n,LL nums){
    char it = *max_element(n.begin(), n.end());
    LL l = (isdigit(it) ? it - '0': it - 'a' + 10) + 1;
    LL r = 1e18;
    while(l < r){
       LL mid = l+r>>1;
       LL t = convert(n,mid);
       if(t >= nums || t < 0) r = mid;
       else l = mid + 1;
    }
    if(convert(n,r) == nums) return r;
    return -1;
}

void solve(){
    string a,b;LL tag,radix;
    cin >> a >> b >> tag >> radix;
    LL flag = tag == 1 ? find_decimal(b,convert(a,radix)) : find_decimal(a,convert(b,radix));
    if(flag != -1){
        printf("%lld\n",flag);
    }else puts("Impossible");
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1011 World Cup Betting (20 分)

  • 题目大意:
    找出最大值并根据题目要求,输入答案

  • 题目解析:
    模拟题意即可

bet 打赌,下注
manner 方式,礼貌,态度,举止
lottery 彩票
triple 三倍
tie 平局,并列,平手

英语单词:

assign 分配,指定,指派,赋值
odd 奇怪的,奇数的,球险胜
correspond 相当,相符,类似于
profit 利益,获利
character 特性,描述,人物,字符

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e5+10;

typedef pair<int,int> pii;
typedef long long LL;

string alp="WTL";

void solve(){
    vector<char> ans;
    double sum = 1;
    for(int i = 0; i < 3; i ++ ){
        char c = 'W';double x;cin>>x;
        for(int j = 1; j < 3; j ++ ){
            double t;cin>>t;
            if(t > x) x = t,c = alp[j];
        }
        ans.push_back(c);
        sum *= x;
    }
    for(int i = 0; i < ans.size(); i ++ ){
        if(i) cout<<' ';
        cout<<ans[i];
    }
    printf(" %.2f",(sum*0.65 - 1)*2);
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1012 The Best Rank (25 分)

  • 题目大意:
    找出每个id的每课成绩和平均成绩的排名

  • 题目解析:
    结构体排序,不同id之间比较相同的科目

核心代码:

bool cmp(Stu a,Stu b){
    return a.score[scoreby] > b.score[scoreby];
}
英语单词:

respect to 关心,考虑,尊敬
symbol 符号,象征,标志

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e6+10;

typedef pair<int,int> pii;
typedef long long LL;

struct Stu{
    int id,best;
    int score[4],rank[4];
};

int n,m;
int scoreby = -1;

bool cmp(Stu a,Stu b){
    return a.score[scoreby] > b.score[scoreby];
}

void solve(){
    cin >> n >> m;
    vector<Stu> stu(n);
    for(int i = 0; i < n; i ++ ){
        int id;cin>>id;
        stu[i].id = id;
        for(int j = 1; j < 4; j ++ ){
            cin >> stu[i].score[j];
        }
        stu[i].score[0] = accumulate(stu[i].score+1,stu[i].score+4,0)/3;
    }
    for(scoreby = 0; scoreby < 4; scoreby ++){
        sort(stu.begin(),stu.end(),cmp);
        stu[0].rank[scoreby] = 1;
        for(int i = 1; i < n; i ++ ){
            if(stu[i].score[scoreby] != stu[i - 1].score[scoreby])
                stu[i].rank[scoreby] = i + 1;
            else
                stu[i].rank[scoreby] = stu[i - 1].rank[scoreby];
        }
    }
    unordered_map<int,pair<int,int>> index;
    for(int i = 0; i < n; i ++ ){
        int minr = stu[i].rank[0];
        int best = 0;
        for(int j = 1; j < 4; j ++ ){
            if(stu[i].rank[j] < minr) minr = stu[i].rank[j],best = j;
        }
        index[stu[i].id] = {minr,best};
    }
    string alp = "ACME";
    while(m --){
        int id; cin >> id;
        if(!index.count(id)) puts("N/A");
        else printf("%d %c\n",index[id].first,alp[index[id].second]);
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1013 Battle Over Cities (25 分)

  • 题目大意:
    当一个城市被占领的时候,这个城市所连接的所有道路都会关闭。求需要修几条路才能让其他城市联通。

  • 题目解析:
    连通图问题,找出所有连通图,每个图连接一条边即可。

英语单词:

check 检查,审查
battle 战争,斗争

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1010;

typedef pair<int,int> pii;
typedef long long LL;

int n,m,k;
vector<int> g[N];
bool vis[N];

void dfs(int u){
    vis[u] = true;
    for(int j : g[u]){
        if(vis[j]) continue;
        dfs(j);
    }    
}

int count(int root){
    memset(vis,false,sizeof vis);
    vis[root] = true;
    int cnt = 0;
    for(int i = 1; i <= n; i ++ ){
        if(!vis[i]) dfs(i),cnt+=1;
    }
    return cnt;
}

void solve(){
    cin >> n >> m >> k;
    for(int i = 0; i < m; i ++){
        int a,b;cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    while(k --){
        int rt; cin >> rt;
        printf("%d\n",count(rt)-1);
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1014 Waiting in Line (30 分)

  • 题目大意:
    银行有N个窗口,每个窗口前面占M个顾客,其他的顾客在黄线外面等待,如果前面有人走,黄线后面的就紧接着排队。
    注意:银行8点开门,17点结束

  • 题目解析:
    比较麻烦的模拟题QWQ。

英语单词:

be served as 被充当,被服务
note that 注意
behind 后面

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1010;

typedef pair<int,int> pii;
typedef long long LL;

struct Node{
    int poptime,endtime;
    queue<int> q;
};

void solve(){
    int n,m,k,q;cin>>n>>m>>k>>q;
    vector<Node> window(n+1);
    vector<int> tim(k+1),result(k+1);
    vector<int> sorry(k+1,false);
    for(int i = 1; i <= k; i ++ ) cin>>tim[i];
    int idx = 1;
    for(int i = 1; i <= m; i ++ ){
        for(int j = 1; j <= n; j ++ ){
            if(idx <= k){
                window[j].q.push(tim[idx]);
                if(window[j].endtime >= 540) sorry[idx] = true;
                window[j].endtime += tim[idx];
                if(i == 1) window[j].poptime = window[j].endtime;
                result[idx++] = window[j].endtime;
            }
        }
    }
    while(idx <= k){
        int tmpmin = window[1].poptime,tmpwindow = 1;
        for(int i = 2; i <= n; i ++ ){
            if(tmpmin > window[i].poptime){
                tmpmin = window[i].poptime;
                tmpwindow = i;
            }
        }
        window[tmpwindow].q.pop();
        window[tmpwindow].q.push(tim[idx]);
        window[tmpwindow].poptime += window[tmpwindow].q.front();
        if(window[tmpwindow].endtime >= 540) sorry[idx] = true;
        window[tmpwindow].endtime += tim[idx];
        result[idx++] = window[tmpwindow].endtime;
    }
    while(q--){
        int query;cin>>query;
        int minute = result[query];
        if(sorry[query]) puts("Sorry");
        else printf("%02d:%02d\n",(minute + 480)/60,(minute + 480)%60);
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1015 Reversible Primes (20 分)

  • 题目大意:
    可逆素数:本身是素数并且转换为D进制反转后也是素数
  • 题目解析:
    进制转换
英语单词:
代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1010;

typedef pair<int,int> pii;
typedef long long LL;

int rever(int n,int radix){
    string s = "";
    do{
        s += n%radix+'0';
        n/=radix;
    }while(n != 0);
    int sum = 0,d = 1;
    for(int i = s.size() - 1; i >= 0; i --){
        sum += d*(s[i] - '0');
        d *= radix;
    }
    return sum;
}

bool isprime(int n){
    if(n < 2) return false;
    for(int i = 2; i <= n/i; i ++ ){
        if(n % i == 0){
            return false;
        }
    }
    return true;
}

void solve(){
    int n,radix;
    while(scanf("%d%d",&n,&radix) != 1){
        int nn = rever(n,radix);
        if(isprime(nn) && isprime(n)) puts("Yes");
        else puts("No");
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1016 Phone Bills (25 分)

  • 题目大意:
    给你一堆电话记录,找到在线和离线的时间段,计算费用,ojk?
  • 题目解析:
    时间转换,排序
英语单词:

toll 通行费,敲
chronologically 按年代地,从历史上,按时间顺序

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 2e3+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

struct Node{
    string name;
    int status,month,tim,day,hour,minute;    
};

int n;
int rate[N];

bool cmp(Node a,Node b){
    if(a.name != b.name)
        return a.name<b.name;
    if(a.tim != b.tim)
        return a.tim<b.tim;
}

double billcount(Node call){
    double cost = rate[call.hour]*call.minute+rate[24]*60*call.day;
    for(int i = 0; i < call.hour; i ++) cost += rate[i]*60;
    return cost/100.0;
}

void solve(){
    for(int i = 0; i < 24; i ++ ){
        cin>>rate[i];
        rate[24] += rate[i];
    }    
    cin>>n;
    vector<Node> data(n);
    for(int i = 0; i < n; i ++ ){
        cin>>data[i].name;
        scanf("%d:%d:%d:%d",&data[i].month,&data[i].day,&data[i].hour,&data[i].minute);
        string tmp;cin>>tmp;
        data[i].status = (tmp=="on-line")?1:0;
        data[i].tim = data[i].day*24*60+data[i].hour*60+data[i].minute;
    }
    sort(data.begin(),data.end(),cmp);
    map<string,vector<Node>> customer;
    for(int i = 1; i < n; i ++ ){
        if(data[i].name == data[i - 1].name && data[i-1].status == 1 && data[i].status == 0 )
        {
            customer[data[i - 1].name].push_back(data[i - 1]);
            customer[data[i].name].push_back(data[i]);
        }
    }
    for(auto it : customer){
        vector<Node> tmp = it.second;
        cout<<it.first;
        printf(" %02d\n",tmp[0].month);
        double sum = 0;
        for(int i = 1; i < tmp.size(); i += 2){
            double cost = billcount(tmp[i]) - billcount(tmp[i-1]);
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n",
            tmp[i-1].day,tmp[i-1].hour,tmp[i-1].minute,tmp[i].day,tmp[i].hour,tmp[i].minute,
            tmp[i].tim-tmp[i-1].tim,cost);
            sum += cost;
        }
        printf("Total amount: $%.2f\n",sum);
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1017 Queueing at Bank (25 分)

  • 题目大意:
    所有客户占到黄线外面,有K个窗口,窗口可以服务就去,8点开门,17点关门。

  • 题目解析:
    先来先服务辣

英语单词:
代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

struct Node{
    int come,wait;
}p[N];

int n,k;

bool cmp(Node a,Node b){
    return a.come < b.come;
}

void solve(){
    cin >> n >> k;
    int cnt = 0;
    for(int i = 1; i <= n; i ++ ){
        int hh,mm,ss,wait;
        scanf("%d:%d:%d %d",&hh,&mm,&ss,&wait);
        int come = hh*60*60+mm*60+ss;
        if(come > 17*60*60) continue;
        p[++cnt].come = come;
        p[cnt].wait = wait*60;
    }
    sort(p+1,p+cnt+1,cmp);
    priority_queue<int,vector<int>,greater<int>> q;
    for(int i = 1; i <= k; i ++ ) q.push(8*60*60);
    double sum = 0;
    for(int i = 1; i <= cnt; i ++ ){
        int tt = q.top();q.pop();
        if(tt <= p[i].come) q.push(p[i].come+p[i].wait);
        else{
            sum += tt-p[i].come;
            q.push(tt+p[i].wait);
        }
        
    }
    if(cnt) printf("%.1f",sum/60/cnt);
    else puts("0.0");
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1018 Public Bike Management (30 分)

  • 题目大意:
    找出一个最短路径,其中需要补充的和带回去的最少。

  • 题目解析:
    Djikstra+DFS

  • 注意:
    不能单独用Dijkstra,因为不能满足最优情况(不能保证需要最少或者带回去的最少),第二、三标尺只能通过遍历所有解找出最优解。

英语单词:

the above 以上所述
vertex 顶点
illustrate 说明,证实

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 510;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int cap,sp,n,m;
int g[N][N];
int c[N],dist[N];
bool vis[N];
int  minback,mineed;
vector<int> pre[N];
vector<int> path,tmppath;

void dfs(int u){
    tmppath.push_back(u);
    if(u == 0){
        int back = 0,need = 0;
        for(int i = tmppath.size() - 1; i >= 0; i -- ){
            int v = tmppath[i];
            if(c[v] >= 0) back += c[v];
            else{
                if(back > (0 - c[v])){
                    back += c[v];
                }else{
                    need += (0 - c[v]) - back;
                    back = 0;
                }
            }
        }
        if(need < mineed){
            path = tmppath;
            mineed = need;
            minback = back;
        }else if(need == mineed && back < minback){
            path = tmppath;
            minback = back;
        }
        tmppath.pop_back();
        return ;
    }
    for(int i = 0; i < pre[u].size(); i ++ )
        dfs(pre[u][i]);
    tmppath.pop_back();
}

void dijkstra(){
    memset(dist,0x3f,sizeof dist);
    dist[0] = 0;
    for(int i = 0; i <= n; i ++ ){
        int t = -1;
        for(int j = 0; j <= n; j ++ ){
            if(!vis[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }
        if(t == -1) break;
        vis[t] = true;
        for(int j = 0; j <= n; j ++ ){
            if(vis[j] || g[t][j] == inf) continue;
            if(dist[j] > dist[t] + g[t][j]){
                dist[j] = dist[t] + g[t][j];
                pre[j].clear();
                pre[j].push_back(t);
            }else if(dist[j] == dist[t] + g[t][j]){
                pre[j].push_back(t);
            }
        }
    }
}

void solve(){
    cin >> cap >> n >> sp >> m;
    for(int i = 1; i <= n; i ++ ){
        cin>>c[i];
        c[i] -= cap/2;
    }
    memset(g,0x3f,sizeof g);
    for(int i =  1; i <= m; i ++ ){
        int a,b,c;cin>>a>>b>>c;
        g[a][b] = g[b][a] = c;
    }
    dijkstra();
    minback = mineed = 1e9;
    dfs(sp);
    printf("%d 0",mineed);
    for(int i = path.size() - 2; i >= 0; i --){
        printf("->%d",path[i]);
    }
    printf(" %d",minback);
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1019 General Palindromic Number (20 分)

  • 题目大意:
    判断一个以基地为b的数字N是否是回文数字
  • 题目解析:
    回文数,进制抓换
  • 注意:
    如果用字符串存的话,要用字符数组存。
    当b<=10可以用字符串存。
英语单词:

palindromic adj. 回文的
be applied to 被用于,应用于

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 510;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

vector<string> ans;

bool judge(){
    int len = ans.size();
    for(int i = 0,j = len - 1; i < j; i ++,j --)
        if(ans[i] != ans[j]) return false;
    return true;
}

void show(){
    for(int i = 0; i < ans.size(); i ++ ){
        if(i) cout<<" ";
        cout<<ans[i];
    }
}
void convert(int n,int radix){
    vector<string> s;
    do{
        s.push_back(to_string(n%radix));
        n/=radix;
    }while(n != 0);
    reverse(s.begin(),s.end());
    ans = s;
}

void solve(){
    int n,base;
    cin >> n >> base;
    convert(n,base);
    if(judge()){
        puts("Yes");
    }else puts("No");
    show();
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1020 Tree Traversals (25 分)

  • 题目大意:
    给出后序和中序,求层序
  • 题目解析:
    二叉树的遍历问题
英语单词:

traversal 遍历,穿越

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 110;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int n;
int in[N],post[N];
vector<pii> level;
unordered_map<int,int> pos;
int cnt = 10;

void dfs(int pr,int il,int ir,int u){
    if(il > ir) return ;
    int root = post[pr];
    int ri = pos[root];
    level.push_back({u,root});
    dfs(pr-(ir-ri)-1,il,ri-1,u*2);
    dfs(pr-1,ri+1,ir,u*2+1);
}

void solve(){
    cin >> n;
    for(int i = 0; i < n; i ++ ) cin >> post[i];
    for(int i = 0; i < n; i ++ ) cin >> in[i],pos[in[i]] = i;
    dfs(n-1,0,n-1,1);
    sort(level.begin(),level.end());
    bool flag = false;
    for(auto u : level){
        if(flag) cout<<" ";
        flag = true;
        cout<<u.second;
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1021 Deepest Root (25 分)

  • 题目大意:
    给你一个图,是一颗树或者多棵树。若是多颗树输出有多少棵树。如果是一棵树,找出一个根使得这棵树的高度最大

  • 题目解析:
    树的直径问题,首先任意找个点v遍历离这个点最远的点u,然后用那个最远的点u再次遍历这棵树,找出最大的高度并且记录这些点。

英语单词:

acyclic 非循环的
hence 因此,所以
In case 万一,如果
component 组件,部件,成分

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int n;
vector<int> g[N];
bool vis[N];
vector<int> tmp;
set<int> alls;
int st,maxv;

void dfs(int u,int level){
    if(level > maxv){
        tmp.clear();
        maxv = level;
        tmp.push_back(u);
    }else if(level == maxv){
        tmp.push_back(u);
    }
    vis[u] = true;
    for(auto v : g[u]) if(!vis[v]) dfs(v,level+1);
}

int count(){
    int cnt = 0;
    memset(vis,0,sizeof vis);
    for(int i = 1; i <= n; i ++ ){
        if(!vis[i]){
            dfs(i,1),cnt++;
            if(i == 1){
                if(tmp.size() != 0) st = tmp[0];
                for(auto v : tmp) alls.insert(v);
            }
        }
    }
    return cnt;
}

void solve(){
    cin >> n;
    for(int i = 0; i < n - 1; i ++ ){
        int a,b;cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int cnt = count();
    if(cnt != 1) printf("Error: %d components\n",cnt);
    else{
        memset(vis,0,sizeof vis);
        tmp.clear();
        maxv = 0;
        dfs(st,1);
        for(auto v : tmp) alls.insert(v);
        for(auto v : alls) cout<<v<<endl;
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1022 Digital Library (30 分)

  • 题目大意:
    给出书籍的一些信息,根据这些信息来查找出符合信息的书的ID号
  • 题目解析:
    模拟题
英语单词:

abstract 摘要,文摘,抽象的,作品
assign 分配
assume 假设

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int n,m;
map<string,vector<string>> info;

void solve(){
    cin >> n;
    for(int i = 0; i < n; i ++ ){
        string id;cin>>id;
        string s;
        for(int j = 0; j < 3; j ++ ){
            getline(cin,s);
            info[s].push_back(id);
        }
        getline(cin,s);
        stringstream ss(s);
        while(ss>>s) info[s].push_back(id);
        for(int j = 0; j < 2; j ++ ){
            getline(cin,s);
            info[s].push_back(id);
        }
    }
    cin>>m;
    getchar();
    while(m --){
        string op;
        getline(cin,op);
        cout<<op<<endl;
        op = op.substr(3,op.size());
        vector<string> ids = info[op];
        sort(ids.begin(),ids.end());
        for(int i = 0; i < ids.size(); i ++ ) printf("%s\n",ids[i].c_str());
        if(!ids.size()) puts("Not Found");
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1023 Have Fun with Numbers (20 分)

  • 题目大意:
    判断这个数字的两倍是否于初始数字的数字排列一样。最后一行,输出这个数字。
  • 题目解析:
    高精度问题
英语单词:

duplication 复制品,重复
exactly 恰好,正确的,精确地
permutation 排列
property 所有物,财产,特性,性质
that is 也就是说,即

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

map<int,int> hs;
vector<int> A,C;

vector<int> add(vector<int> &A, vector<int> &B){
    if(A.size() < B.size()) return add(B,A);
    int t = 0;
    vector<int> C;
    for(int i = 0; i < A.size(); i ++ ){
        t += A[i];
        if(i < B.size()) t += B[i];
        C.push_back(t%10);
        t/=10;
    }
    if(t) C.push_back(t);
    return C;
}

bool judge(){
    for(auto c : C){
        hs[c] -= 1;
        if(hs[c] == 0) hs.erase(c);
    }
    if(hs.size() == 0)
    return true;
    else 
    return false;
}

void solve(){ 
    string s;cin>>s;
    for(auto c : s) hs[c-'0'] += 1;
    for(int i = s.size() - 1; i >= 0; i --) A.push_back(s[i]-'0');
    C = add(A,A);
    if(judge()) puts("Yes");
    else puts("No");
    for(int i = C.size() - 1; i >= 0; i -- ) cout<<C[i];
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1024 Palindromic Number (25 分)

  • 题目大意:
    给一个数字N,判断是否能经过K次翻转相加于原数字成为回文数字

  • 题目解析:
    高精度

  • 注意:初始数字是回文数字,则直接输出0

英语单词:

via 通过,经过

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

vector<int> A,B;

vector<int> add(vector<int> &A,vector<int> &B){
    if(A.size() < B.size()) return add(B,A);
    int t = 0;
    vector<int> C;
    for(int i = 0; i < A.size(); i ++ ){
        t += A[i];
        if(i < B.size()) t += B[i];
        C.push_back(t%10);
        t/=10;
    }
    if(t) C.push_back(t);
    return C;
}

bool judge(vector<int> &A){
    for(int i = 0,j = A.size() - 1; i < j; i ++,j--){
        if(A[i] != A[j]) return false;
    }
    return true;
}

void solve(){ 
    string s;cin>>s;
    int k;cin>>k;
    for(int i = s.size()-1; i >= 0; i --) A.push_back(s[i]-'0');
    int i = 0;
    for(i = 0; i < k; i ++ ){
        if(judge(A)) break;
        B = A;
        reverse(B.begin(),B.end());
        A = add(A,B);
    }
    for(int i = A.size() - 1; i >= 0; i --) cout<<A[i];
    puts("");
    printf("%d",i);
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1025 PAT Ranking (25 分)

  • 题目大意:
    PAT考试有几个考场,最后合并排名。
    求当前考场排名,合并考场后的排名,ojk?
  • 题目解析:
    排序题
英语单词:

simultaneously 同时地
immediately 立刻地
generate 产生,生成
testee 测试对象,受测者,考生
registration 登记,注册

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int n,k;

struct Stu{
    string id;
    int score,rk1,rk2,pos;
};

bool cmp(Stu a,Stu b){
    return a.score!=b.score?a.score>b.score:a.id<b.id;
}

void solve(){ 
    cin >> n;
    vector<Stu> stus; 
    for(int i = 1; i <= n; i ++ ){
        cin >> k;
        vector<Stu> tmp;
        for(int j = 1; j <= k; j ++ ){
            string id;int score;
            Stu stu;
            cin>>id>>score;
            stu.id = id,stu.score = score;
            stu.pos = i;stu.rk1=stu.rk2=0;
            tmp.push_back(stu);
        }
        sort(tmp.begin(),tmp.end(),cmp);
        tmp[0].rk2 = 1;
        stus.push_back(tmp[0]);
        for(int i = 1; i < k; i ++ ){
            if(tmp[i].score != tmp[i - 1].score){
                tmp[i].rk2 = i + 1;
            }else{
                tmp[i].rk2 = tmp[i - 1].rk2;
            }
            stus.push_back(tmp[i]);
        }
    }
    sort(stus.begin(),stus.end(),cmp);
    stus[0].rk1 = 1;
    int nn = stus.size();
    printf("%d\n",nn);
    printf("%s %d %d %d\n",stus[0].id.c_str(),stus[0].rk1,
        stus[0].pos,stus[0].rk2);
    for(int i = 1; i < nn; i ++ ){
        if(stus[i].score != stus[i - 1].score){
            stus[i].rk1 = i + 1;
        }else stus[i].rk1 = stus[i - 1].rk1;
        printf("%s %d %d %d\n",stus[i].id.c_str(),stus[i].rk1,
        stus[i].pos,stus[i].rk2);
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1026 Table Tennis (30 分)

乒乓球暂时不写,QWQ

  • 题目大意:
  • 题目解析:
英语单词:
代码如下:

1027 Colors in Mars (20 分)

  • 题目大意:
    在火星上,它们用基地13来代替16。给出三个十进制数转换为13进制。如果是单个数字,前面需要补0

  • 题目解析:
    进制转换

英语单词:

upper-case 大写字母
decimal 十进制的,小数的

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int red,green,blue;
string alp = "0123456789ABC";

string convert(int n,int radix){
    string s = "";
    do{
        s += alp[n%radix];
        n/=radix;
    }while(n!=0);
    reverse(s.begin(),s.end());
    if(s.size() == 1) s = "0" + s;
    return s;
}

void solve(){ 
    cin >> red >> green >> blue;
    string ans = "#";
    ans += convert(red,13) + convert(green,13) + convert(blue,13);
    printf("%s",ans.c_str());
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1028 List Sorting (25 分)

  • 题目大意:
    如果C=1,对ID进行递增排序;C=2,对名字进行非递减排序;C=3,对成绩进行非递减排序;
  • 题目解析:
    排序题
英语单词:

imitate 模仿,仿效,仿制
inclusive 包含的,对外开放的,包容广阔的

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

struct Stu{
    string id,name;
    int score;
};

bool cmp1(Stu a,Stu b){
    return a.id < b.id;    
}

bool cmp2(Stu a,Stu b){
    if(a.name != b.name) return a.name<b.name;
    return a.id < b.id;
}

bool cmp3(Stu a,Stu b){
    if(a.score != b.score) return a.score<b.score;
    return a.id < b.id;
}

void solve(){ 
    int n,k;cin>>n>>k;
    vector<Stu> stus;
    for(int i = 0; i < n; i ++ ){
        string id,name;int score;
        cin>>id>>name>>score;
        stus.push_back({id,name,score});
    }
    if(k == 1) sort(stus.begin(),stus.end(),cmp1);
    else if(k == 2) sort(stus.begin(),stus.end(),cmp2);
    else sort(stus.begin(),stus.end(),cmp3);
    for(auto stu : stus){
        cout<<stu.id<<" "<<stu.name<<" "<<stu.score<<endl;
    }
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1029 Median (25 分)

  • 题目大意:
    给两个序列,找到合并后序列里的中位数
  • 题目解析:
    排序题
英语单词:

median 中值,中位数

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 1e4+10;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int n,m;

void solve(){ 
    cin >> n;
    vector<LL > A;
    for(int i = 0; i < n; i ++ ){
        int x;cin>>x;
        A.push_back(x);
    }
    cin >> m;
    for(int i = 0; i < m; i ++ ){
        int x;cin>>x;
        A.push_back(x);
    }
    sort(A.begin(),A.end());
    cout<<A[(n+m-1)/2];
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}

1030 Travel Plan (30 分)

  • 题目大意:
    找出起始位置到终点的最短距离,第二标尺最小花费
  • 题目解析:
    Dijkstra裸题
英语单词:

destination 目的地,终点

代码如下:
#include<bits/stdc++.h>

using namespace std;

const int N = 510;
const int inf = 0x3f3f3f3f;

typedef pair<int,int> pii;
typedef long long LL;

int n,m,st,ed;
int g[N][N],w[N][N];
bool vis[N];
int dist[N],cost[N],path[N];
vector<int> tmp;

void dijkstra(){
    memset(dist,0x3f,sizeof dist);
    memset(cost,0x3f,sizeof cost);
    dist[st] = 0;
    cost[st] = 0;
    for(int i = 0; i < n; i ++ ){
        int t = -1;
        for(int j = 0; j < n; j ++ ){
            if(!vis[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }
        vis[t] = true;
        for(int j = 0; j < n; j ++ ){
            if(dist[j] > dist[t] + g[t][j]){
                dist[j] = dist[t] + g[t][j];
                cost[j] = cost[t] + w[t][j];
                path[j] = t;
            }else if(dist[j] == dist[t] + g[t][j]){
                if(cost[j] > cost[t] + w[t][j]){
                    cost[j] = cost[t] + w[t][j];
                    path[j] = t;
                }
            }
        }
    }
}

void dfs(int u){
    tmp.push_back(u);
    if(u == st){
        return ;
    }
    dfs(path[u]);
}

void solve(){ 
    cin >> n >> m >> st >> ed;
    memset(g,0x3f,sizeof g);
    memset(w,0x3f,sizeof w);
    for(int i = 0; i < m; i ++ ){
        int a,b,c1,c2;cin>>a>>b>>c1>>c2;
        g[a][b] = g[b][a] = c1;
        w[a][b] = w[b][a] = c2;
    }
    dijkstra();
    dfs(ed);
    reverse(tmp.begin(),tmp.end());
    bool ok = false;
    for(auto x : tmp){
        if(ok) cout<<" ";
        cout<<x;
        ok=true;
    }
    printf(" %d %d",dist[ed],cost[ed]);
}

int main(){
    int _; _=1;
    while(_--) solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值