【2021-01-21】PAT (Advanced Level) Practice

1001 A+B Format (20分)

  简单的模拟题。就是整数类型的加减法然后对得到的结果进行处理即可。

1002 A+B for Polynomials (25分)

  简单的多项式相加,相同的系数进行加法运算就可以了。注意要点,系数可能为负,注意判断条件的使用。

1003 Emergency (25分)

  这道题求解的是最短路径问题,在最短路径的基础上,再加上求解最短路径的条数以及最短路径中守卫数量最多的一条最短路径。
  首先是一个单源的最短路径问题,这个可以用Dijkstra算法求解。但是我们要在更新最短路径的时候,同时更新最短路径的条数以及守卫的最大数量,分别针对相等和大于的两种情况处理即可。

#include<bits/stdc++.h>
#define close ios::sync_with_stdio(false)
using namespace std;
const int maxn=3e5;
const int INF=0x3f3f3f3f;
struct Edge{
    
    
    int from,to,w;
    Edge(int a,int b,int c){
    
    from=a;to=b;w=c;}
};
vector<Edge> e[maxn];
int rescue_team[510];
struct s_node{
    
    
    int id,n_dis;
    s_node(int b,int c){
    
    id=b;n_dis=c;}
    bool operator <(const s_node &a)const{
    
    
        return n_dis>a.n_dis;
    }
};
int n,m;
int path_num[510],tot_num[510];
void Dijkstra(int s,int f)
{
    
    
    int dis[510];bool done[510];
    for(int i=0;i<n;++i) {
    
    dis[i]=INF;done[i]=false;path_num[i]=0;tot_num[i]=0;}
    dis[s]=0;path_num[s]=1;tot_num[s]=rescue_team[s];
    priority_queue<s_node> Q;
    Q.push(s_node(s,dis[s]));
    while(!Q.empty())
    {
    
    
        s_node u=Q.top();Q.pop();
        if(done[u.id]) continue;
        done[u.id]=true;
        for(int i=0;i<e[u.id].size();++i)
        {
    
    
            Edge y=e[u.id][i];
            if(done[y.to]) continue;
            if(dis[y.to]>y.w+u.n_dis){
    
    
                dis[y.to]=y.w+u.n_dis;
                Q.push(s_node(y.to,dis[y.to]));
                path_num[y.to]=path_num[u.id];
                tot_num[y.to]=tot_num[u.id]+rescue_team[y.to];
            }
            else if(dis[y.to]==y.w+u.n_dis){
    
    
                path_num[y.to]+=path_num[u.id];
                tot_num[y.to]=max(tot_num[y.to],tot_num[u.id]+rescue_team[y.to]);
            }
        }
    }
    cout<<path_num[f]<<' '<<tot_num[f]<<endl;
}
int main()
{
    
    
    close;int C1,C2;cin>>n>>m>>C1>>C2;
    for(int i=0;i<n;++i) cin>>rescue_team[i];
    for(int i=0;i<m;++i)
    {
    
    
        int x,y,w;cin>>x>>y>>w;
        e[x].push_back(Edge(x,y,w));
        e[y].push_back(Edge(y,x,w));
    }
    Dijkstra(C1,C2);
}

1004 Counting Leaves(30分)

  (我也不知道这个题为什么值30分…)简单的关于树的深度的题目,DFS跑一遍树,如果这个结点没有子结点,就给这个深度的子结点数+1,否则就继续DFS。

1005 Spell It Right(20分)

  简单的字符串的处理的题目,注意的是各位求和结果是0的特判。

1006 Sign In and Sign Out(25分)

  简单的模拟题,主要是想考察对时间的比较。因为这里是同一天,这里直接采用对时间全部换成秒的形式,即 3600 ∗ h o u r + 60 ∗ m i n u t e + s e c o n d 3600*hour+60*minute+second 3600hour+60minute+second,这样就是一个整数切根据题意没有重复,直接排序即可。

1007 Maximum Subsequence Sum(25分)

  一个非常简单的DP问题,但是却有坑点,可能会被坑在21分-22分。这个题非常常见的思路:如果 d p [ i − 1 ] > 0 dp[i-1]>0 dp[i1]>0(为了保证取到最大值的序列最短,所以前面的子序列的和为0没有贡献),则 d p [ i ] = d p [ i − 1 ] + a [ i ] dp[i]=dp[i-1]+a[i] dp[i]=dp[i1]+a[i];否则 d p [ i ] = a [ i ] dp[i]=a[i] dp[i]=a[i]。那么要求输出取得最大值的子序列的左右端点,我们可以记录状态。
  但这道题的坑点在于,如果按照上述判断的方式,最大值是0的时候可能分为两种情况:一种是所有的数字都是负数,另一种是所有的数字都是负数和0!如果包含0的话一定要注意不能输出原序列的左右端点!

猜你喜欢

转载自blog.csdn.net/CUMT_William_Liu/article/details/112863200