浙大PAT甲级题目

题目链接

https://www.nowcoder.com/pat/5/problems

2019-6-3

1001 Public Bike Management (30)

思路

看完题目就是最短路、数据范围N<500, C<100
要求多条最短路的情况下, 优先选择运出最少、其次是运入最少
考虑一条最短路径、题目要求路径上每个点都要满足C/2。
使用dij搜索, 用一个pre,vector数组, 存放所有的前置节点、组合可以得到所有最短路径
每条最短路 p a t h i path_i pathi一共有 x i x_i xi个结点计算 v a l u e i = ∣ ∑ j = 1 x i c n t j − x i ∗ C / 2 ∣ value_i=|\sum_{j=1}^{x_i}cnt_j - x_i*C/2| valuei=j=1xicntjxiC/2
然后路径按照value排序、value最小的就是问题的解

#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define pb push_back
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
const int N = 1e3+10;
const int INF = 0x3f3f3f3f;

struct node{
   int v,c;
   bool operator < (const node &rhs) const{
       return c>rhs.c;
   }
};


vector<node> G[N];
VI pre[N];
int dis[N];
bool vis[N];
int value[N];
void dij(int n, int t, int &min_cost)
{
   priority_queue<node> que;
   rep(i,0,n+1)dis[i] = INF,vis[i] = false;
   dis[0] = 0;
   que.push((node){0,0});
   bool ret = false;
   while(!que.empty())
   {
       node tp = que.top();que.pop();
       int u = tp.v;
       if (vis[u]) continue;
       vis[u] = true;
       if (tp.c > min_cost)
           return;
       if (u == t)
       {
           min_cost = dis[u];
       }
       rep(i,0,(int)G[u].size())
       {
           int v = G[u][i].v, c = G[u][i].c;
           if (!vis[v] && dis[v] >= dis[u] + c)
           {
               if (dis[v] > dis[u] + c)
               {
                   dis[v] = dis[u] + c;
                   que.push((node){v,dis[v]});
                   pre[v].clear();
                   pre[v].push_back(u);
               }
               else
               {
                   pre[v].push_back(u);
               }
           }
       }
   }
}

VVI paths;
int path[N];
void dfs(int u, int fa, int top)
{
   path[++top] = u;    
   if (u == 0)
   {
       VI tp;
       while(top != -1)
           tp.push_back(path[top--]);
       paths.push_back(tp);
       return;
   }
   rep(i,0,(int)pre[u].size())
   {
       int v = pre[u][i];
       if (v != fa)
       {
           dfs(v, u, top);
       }
   }
}

int main()
{
   int max_c, n, t, m;
   cin>>max_c>>n>>t>>m;
   value[0] = 0;
   rep(i,1,n+1)
   cin>>value[i];
   int x,y,z;
   rep(i,0,m)
   {
       cin>>x>>y>>z;
       G[x].pb((node){y,z});
       G[y].pb((node){x,z});
   }
   int min_cost = INF;
   dij(n,t,min_cost);
   VI ans;
   dfs(t,-1,-1);
   int mmin1 = INF, pos1 = -1, tag = -1;
   int mmin2 = INF, pos2 = -1;
   rep(i,0,(int)paths.size())
   {
       int Sum = 0;
       rep(j,0,(int)paths[i].size())
           Sum += value[paths[i][j]];
       int val = ((int)paths[i].size()-1) * max_c / 2 - Sum;
       if (val >= 0 && mmin1 > val)
       {
           mmin1 = val;
           pos1 = i;
           tag = 1;
       }
       if (tag == -1 && val < 0 && mmin2 > -val)
       {
           mmin2 = -val;
           pos2 = i;
       }
   }
   int pos=-1, mmin=INF;
   if (tag == 1)
   {
       pos = pos1;
       mmin = mmin1;
   }
   if (tag == -1)
   {
       pos = pos2;
       mmin = mmin2;
   }
   if (pos != -1)
   {
       int in = 0, out = 0;
       if (tag == 1)
           out = mmin;
       else
           in = mmin;
       cout << out << ' ';
       int sz = (int)paths[pos].size();
       rep(i,0,sz-1)
       cout << paths[pos][i] << "->";
       cout << paths[pos][sz-1] <<" "<< in << endl;
   }
   return 0;
}

然后上交代码后发现是错的。 看了数据和讨论区才知道, 自行车中心可以,送出和收回的数量可都不为零。
完全没想到啊。这tm。
然后我修改了一下代码。

#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define pb push_back
using namespace std;
typedef vector<int> VI;
typedef vector<VI> VVI;
const int N = 1e3+10;
const int INF = 0x3f3f3f3f;
 
struct node{
    int v,c;
    bool operator < (const node &rhs) const{
        return c>rhs.c;
    }
};
 
 
vector<node> G[N];
VI pre[N];
int dis[N];
bool vis[N];
int value[N];
void dij(int n, int t, int &min_cost)
{
    priority_queue<node> que;
    rep(i,0,n+1)dis[i] = INF,vis[i] = false;
    dis[0] = 0;
    que.push((node){0,0});
    bool ret = false;
    while(!que.empty())
    {
        node tp = que.top();que.pop();
        int u = tp.v;
        if (vis[u]) continue;
        vis[u] = true;
        if (tp.c > min_cost)
            return;
        if (u == t)
        {
            min_cost = dis[u];
        }
        rep(i,0,(int)G[u].size())
        {
            int v = G[u][i].v, c = G[u][i].c;
            if (!vis[v] && dis[v] >= dis[u] + c)
            {
                if (dis[v] > dis[u] + c)
                {
                    dis[v] = dis[u] + c;
                    que.push((node){v,dis[v]});
                    pre[v].clear();
                    pre[v].push_back(u);
                }
                else
                {
                    pre[v].push_back(u);
                }
            }
        }
    }
}
 
VVI paths;
int path[N];
void dfs(int u, int fa, int top)
{
    path[++top] = u;   
    if (u == 0)
    {
        VI tp;
        while(top != -1)
            tp.push_back(path[top--]);
        paths.push_back(tp);
        return;
    }
    rep(i,0,(int)pre[u].size())
    {
        int v = pre[u][i];
        if (v != fa)
        {
            dfs(v, u, top);
        }
    }
}
 
int main()
{
    int max_c, n, t, m;
    cin>>max_c>>n>>t>>m;
    value[0] = 0;
    rep(i,1,n+1)
    cin>>value[i];
    int x,y,z;
    rep(i,0,m)
    {
        cin>>x>>y>>z;
        G[x].pb((node){y,z});
        G[y].pb((node){x,z});
    }
    int min_cost = INF;
    dij(n,t,min_cost);
    VI ans;
    dfs(t,-1,-1);
    int mmin1 = INF, pos1 = -1, tag = -1;
    int mmin2 = INF, pos2 = -1;
    rep(i,0,(int)paths.size())
    {
        int Sum = 0;
        rep(j,0,(int)paths[i].size())
            Sum += value[paths[i][j]];
        int val = ((int)paths[i].size()-1) * max_c / 2 - Sum;
        if (val >= 0 && mmin1 > val)
        {
            mmin1 = val;
            pos1 = i;
            tag = 1;
        }
        if (tag == -1 && val < 0 && mmin2 > -val)
        {
            mmin2 = -val;
            pos2 = i;
        }
    }
    int pos=-1, mmin=INF;
    if (tag == 1)
    {
        pos = pos1;
        mmin = mmin1;
    }
    if (tag == -1)
    {
        pos = pos2;
        mmin = mmin2;
    }
    if (pos != -1)
    {
        int in = 0, out = 0;
        if (tag == 1)
            out = mmin;
        else
            in = mmin;
        cout << out << ' ';
        int sz = (int)paths[pos].size();
        rep(i,0,sz-1)
        cout << paths[pos][i] << "->";
        cout << paths[pos][sz-1] <<" "<< in << endl;
    }
    return 0;
}
  1. Linked List Sorting (25)
    这道题非常坑
    一是题目说是给一个链表, 但却是给了头结点和 其他链表节点, 不只有一条主链, 所以要自己把主链筛选出来
    二是, 当主链为空链时, (也就是头结点为-1)没有说明如何输出, (其实是输出0 -1)
#include<bits/stdc++.h>

using namespace std;
typedef pair<int, string> P;
const int N = 1e5+10;
int n;
map<string, P> mp;
vector<P> node;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    string s,t;
    cin>>s;
    int x;
    for(int i=0;i<n;i++){
        P temp;
        cin>>t>>temp.first>>temp.second;
        mp[t] = temp;
    }
    string p = s;
    while(p!="-1"){
        node.push_back(P(mp[p].first,p));
        p = mp[p].second;
    }
    sort(node.begin(), node.end());
    n = node.size();
    if (n!=0){
        cout<<n<<" "<<node[0].second<<endl;
        for(int i=0;i<n;i++){
            cout<<node[i].second<<" "<<node[i].first<<" "<<(i==n-1?"-1":node[i+1].second)<<endl;
        }
    }else{
        cout<<"0 -1"<<endl;
    }
}

1111 Online Map (30 point(s))

松弛条件修改dijstra
上面自行车那题一样, 但是我发现PAT出的题都是可以不用回溯pre数组, 而是直接把次要条件加入到松弛的判断中就行了,
但是需要注意的是, 如果cost的排序标准变成了两个条件cost[2], 那么priority_queue的关键词应该也要是两个cost[2]。
因为理论上, 等于是把dijstra的距离改成了两个参数综合的距离。
但是代码中我没用, 可能是没有这样的数据

#include<bits/stdc++.h>
#define pb push_back
#define rep(i,l,r) for(int i=l;i<r;i++)
using namespace std;
const int N = 5e2+10;
const int inf = 0x3f3f3f3f;
typedef pair<int, int> P;
int n, m, s, t;
/*
对于A为主要条件, B为次要条件的题目, 可以把AB用一个cost[2]来存放
然后dijstra的算法中,松弛操作可以用一个better函数来判断是否松弛。
void dijstra(){
    init que,vis,dis;
    push(source), set source's parameter to zero;
    while(!que.empty()):
        if vis continue; vis = true
        for all v in G[u]:
            if !vis[v] && can_slack == true:
                slack
                push v to que
}
*/

/* global variant */
struct Node{
    int v, cost[2];
    Node(int _v, int _l, int _t){
        v = _v;
        cost[0] = _l;
        cost[1] = _t;
    }
    Node(){};
};
vector<Node> G[N];
bool vis[N];
int dis[2][N], insec[N], pre[N];//dij parameter
int ans[2][N],  top[2], mincost[2];//to store ans

/*function*/
bool better(int u, int v, Node &tp, int tag){
    if (tag == 0)
        return dis[0][v]==dis[0][u]+tp.cost[0]?dis[1][v] > dis[1][u]+tp.cost[1]:dis[0][v]>dis[0][u]+tp.cost[0];
    else
        return dis[1][v]==dis[1][u]+tp.cost[1]?insec[v] > insec[u]+1:dis[1][v]>dis[1][u]+tp.cost[1];
}

void dij(int tag){
    priority_queue<P, vector<P>, greater<P> > que;
    memset(dis, 0x3f, sizeof (dis));
    memset(dis[1],0x3f,sizeof dis[1]);
    memset(insec,0x3f,sizeof insec);
    memset(vis, 0, sizeof vis);
    memset(pre,-1, sizeof pre);
    dis[0][s] = dis[1][s]= 0;
    insec[s] = 1;
    que.push(P(0,s));
    while(!que.empty()){
        P tp = que.top();que.pop();
        int u = tp.second;
        if (vis[u])continue;
        vis[u] = true;
        for(int i=0;i<(int)G[u].size();i++){
            int v = G[u][i].v;
            if (vis[v])continue;
            if (better(u,v,G[u][i],tag)){ // just to adjust this condition functions
                dis[0][v] = dis[0][u] + G[u][i].cost[0];
                dis[1][v] = dis[1][u] + G[u][i].cost[1];
                insec[v] = insec[u] + 1;
                que.push(P(dis[tag][v], v));
                pre[v] = u;
            }
        }
    }
}
void out(int tag){
    for(int i=top[tag]-1;i>0;i--){
        cout<<ans[tag][i]<<" -> ";
    }cout<<ans[tag][0]<<endl;
}
bool same_array(int *a, int *b, int n, int m){
    if (n != m)return false;
    for(int i=0;i<n;i++) if (a[i] != b[i])return false;
    return true;
}
int main()
{
    //freopen("1111.in","r",stdin);
    ios::sync_with_stdio(false);
    while(cin>>n>>m){
        int x, y, tag, l, t;
        top[0] = top[1] = 0;
        for(int i=0;i<N;i++)G[i].clear();
        while(m--){
            cin>>x>>y>>tag>>l>>t;
            if (tag){
                G[x].pb(Node(y, l, t));
                
            }else{
                G[x].pb(Node(y, l, t));
                G[y].pb(Node(x, l, t));
            }
        }
        cin>>s>>t;
        for(int i=0;i<2;i++){
            dij(i);
            mincost[i] = dis[i][t];
            int p = t;
            while(p!=-1){
                ans[i][top[i]++] = p;
                p = pre[p];
            }
        }
        bool fg = same_array(ans[0], ans[1], top[0], top[1]);
        if (fg){
            cout<<"Distance = "<<mincost[0]<<"; Time = "<<mincost[1]<<": ";
            out(0);
        }else{
            cout<<"Distance = "<<mincost[0]<<": ";
            out(0);
            cout<<"Time = "<<mincost[1]<<": ";
            out(1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值