浙大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
#define rep(i,l,r) for(int i=l;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
#define rep(i,l,r) for(int i=l;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

using namespace std;
typedef pair P;
const int N = 1e5+10;
int n;
map mp;
vector

node; int main() { ios::sync_with_stdio(false); cin>>n; string s,t; cin>>s; int x; for(int i=0;i>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<

1111 Online Map (30 point(s))

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

#include
#define pb push_back
#define rep(i,l,r) for(int i=l;i 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 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, greater

> 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< "; }cout<>n>>m){ int x, y, tag, l, t; top[0] = top[1] = 0; for(int i=0;i>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 = "<

你可能感兴趣的:(搜索,最短路)