其他分享
首页 > 其他分享> > 二刷PAT:advanced1018,1019,1020,1021

二刷PAT:advanced1018,1019,1020,1021

作者:互联网

手热做了四道,还行

1018Public Bike Management

大概就是在一个自行车管理监控系统中,你会实时得到各个站点含有的自行车数,我们需要从PBMC出发到达给出的存在问题的站点使其变成完美状态(也需要使途径的站点变成完美状态,完美状态是指站点的自行车数等于Cmax/2)
去年做的时候学别人直接dfs,做得晕头转向。这回直接拆成dijkstra+dfs思路清晰了很多

利用dijkstra配合前驱结点序列得到最短路径,再利用dfs得到最小返回minback和最小带走mintake

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//c:capacity,n:,sp:index of problem station, m: number of roads
ll c, n, sp, m, r1, r2, ph;
const int inf = 99999999;
ll bk[510]; //current bike
ll dist[510];   //
vector<ll> pre[510], tempath, path;
ll road[510][510];
ll mintake = inf, minback = inf;//dfs
bool visited[510];
//output: bike sent from PBMC
//if the path is not unique(take equal time), output the one that sent minimum bike to PBMC
void dfs(ll curcity)
{
    tempath.push_back(curcity);
    if (curcity == 0)   //PBMC,清算take和back
    {
        ll take = 0, back = 0;
        for (ll i = tempath.size() - 1; i >= 0; --i)
        {
            ll id = tempath[i];
            if (bk[id] > 0) {back += bk[id];}   //back
            else 
            {
                if (back > (0 - bk[id]))
                {
                    back += bk[id];
                }
                else 
                {
                    take += ((0 - bk[id]) - back);
                    back = 0;
                }
            }
        }
        if (take < mintake) 
        {
            mintake = take;
            minback = back;
            path = tempath;
        }
        else if (take == mintake and back < minback)
        {
            minback = back;
            path = tempath;
        }
        tempath.pop_back();
        return;
    }
    for (ll i = 0; i < pre[curcity].size(); ++i)
    {
        dfs(pre[curcity][i]);
    }
    tempath.pop_back(); 
}
int main(void)
{
    cin>>c>>n>>sp>>m;
    for (ll i = 0; i < 510; ++i) {dist[i] = inf;}
    for (ll i = 0; i < 510; ++i)
    {
        for (ll j = 0; j < 510; ++j) {road[i][j] = inf;}
    }
    memset(visited, false, sizeof(visited));
    for(ll i = 1; i <= n; ++i) 
    {
        cin>>bk[i];
        bk[i] = bk[i] - c / 2;  //预处理
    }
    for (ll i = 0; i < m; ++i)
    {
        cin>>r1>>r2>>ph;
        road[r1][r2] = road[r2][r1] = ph;
    }
    for (ll i = 0; i < 510; ++i) {road[i][i] = 0;}
    dist[0] = 0;
    //dijkstra求最短路径
    for (ll i = 0; i <= n; ++i)
    {
        ll index = -1, tmpdist = inf;
        for(ll j = 0; j <= n; ++j)
        {
            if (!visited[j] and dist[j] < tmpdist)
            {
                tmpdist = dist[j];
                index = j;
            }
        }
        if (index == -1) {break;}
        visited[index] = 1;
        for (ll j = 0; j <= n; ++j)
        {
            if (!visited[j] and road[j][index] != inf)
            {
                if (road[j][index] + dist[index] < dist[j])
                {
                    dist[j] = road[j][index] + dist[index];
                    pre[j].clear();
                    pre[j].push_back(index);
                }
                else if (road[j][index] + dist[index] == dist[j])
                {
                    pre[j].push_back(index);
                }
            }
        }
    }
    //dfs确定最小send和最小take
    dfs(sp);
    cout<<mintake<<" ";
    ll index = 0;
    for (ll i = path.size() - 1; i >= 0; --i)
    {
        if (index == 0)
        {
            cout<<path[i];
            index++;
        }
        else {cout<<"->"<<path[i];}
    }
    cout<<" "<<minback;
    return 0;
}

1019.General Palindromic Number

有手就行,直接上代码

#include <bits/stdc++.h>
using ll = long long;
using namespace std;
ll digit, n;
int main(void)
{
    cin>>n>>digit;
    //if (n > 0 % n < 10) {cout<<"Yes"<<endl; cout<<n<<endl; return 0;}
    vector<ll> ans;
    while (n)
    {
        ans.push_back(n % digit);
        n /= digit;
    }
    ll i = 0, j = ans.size() - 1;
    bool f = true;
    while (i < j)
    {
        if (ans[i] != ans[j]) {f = false; break;}
        i += 1;
        j -= 1;
    }
    if (f) {cout<<"Yes"<<endl;}
    else {cout<<"No"<<endl;}
    for (ll index = ans.size() - 1; index >= 0; --index)
    {
        if (index == 0) {cout<<ans[index];}
        else {cout<<ans[index]<<" ";}
    }
    return 0;
}

1020.Tree Traverals感觉一般般吧,通过后序遍历和中序遍历递归得到树结构,之前leetcode树的题做了不少,直接搬了leetcode给的树板子,层序遍历(广度优先)也算是老生常谈
直接代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll post[50];
ll in[50];
ll n;
class TreeNode
{
    public:
        ll val;
        TreeNode* left;
        TreeNode* right;
        TreeNode():left(nullptr), right(nullptr){}
        TreeNode(ll val):val(val), left(nullptr), right(nullptr){}
};
TreeNode* traversal(ll root, ll left, ll right)
{
    if (left > right) {return nullptr;}
    ll idx = left;
    while (post[root] != in[idx]) {idx++;}
    TreeNode* t = new TreeNode(post[root]);
    t->left = traversal(root - (right - idx) - 1, left, idx - 1);
    t->right = traversal(root - 1, idx + 1, right);
    return t;
}
int main(void)
{
    ll n;
    cin>>n;
    for (ll i = 0; i < n; ++i) {cin>>post[i];}
    for (ll i = 0; i < n; ++i) {cin>>in[i];}
    TreeNode* root = traversal(n - 1, 0, n - 1);
    queue<TreeNode*> q;
    q.push(root);
    ll idx = 0;
    while (!q.empty())
    {
        ll len = q.size();
        for (ll i = 0; i < len; ++i)
        {
            TreeNode* tmp = q.front();
            q.pop();
            if (idx == 0) {cout<<tmp->val; idx++;}
            else {cout<<" "<<tmp->val;}
            if (tmp->left) {q.push(tmp->left);}
            if (tmp->right) {q.push(tmp->right);}
        }
    }
    return 0;
}

1021.Deepest Root
这个的确不是太难,主要是连通分量判断吧,只要输入点同时已经被访问过,那么连通分量就会加一

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
vector<vector<ll>> road(10001);
bool visited[10001];
ll n, r1, r2;
ll maxpath, finpath;
void dfs(ll root, ll curlen)
{
    if (visited[root]) {return;}
    visited[root] = true;
    curlen += 1;
    if (curlen > maxpath) {maxpath = curlen;}
    for (ll i = 0; i < road[root].size(); ++i)
    {
        dfs(road[root][i], curlen);
    }
}
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for (ll i = 1; i <= n; ++i) {visited[i] = false;}
    ll connected = 1;
    for (ll i = 0; i < n - 1; ++i)
    {
        cin>>r1>>r2;
        road[r1].push_back(r2);
        road[r2].push_back(r1);
        if (visited[r1] and visited[r2]) {connected += 1;}
        else {visited[r1] = visited[r2] = true;}
        //需要在这里判断连通分量的个数
    }
    if (connected > 1) {cout<<"Error: "<<connected<<" components"<<endl; return 0;}
    vector<ll> ans;
    for (ll i = 1; i <= n; ++i)
    {
        for (ll j = 1; j <= n; ++j) {visited[j] = false;}
        maxpath = 0;
        dfs(i, 0);
        if (maxpath > finpath)
        {
            ans.clear();
            ans.push_back(i);
            finpath = maxpath;
        }
        else if (maxpath == finpath) {ans.push_back(i);}
    }
    for (ll i = 0; i < ans.size(); ++i) 
    {
        cout<<ans[i]<<endl;
    }
    return 0;
}

后面三个题没什么营养,也会de几次,并不是一遍过。
睡了睡了。

标签:index,1021,1020,++,advanced1018,back,visited,ll,road
来源: https://blog.csdn.net/m0_48775319/article/details/119089169